Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace NSNumber with JMESNumber #10

Merged
merged 4 commits into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ on:

jobs:
macos:
runs-on: macOS-13
runs-on: macOS-14
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All @@ -36,10 +36,9 @@ jobs:
strategy:
matrix:
tag:
- swift:5.8
- swift:5.9
- swift:5.10
- swiftlang/swift:nightly-6.0-jammy
- swift:6.0
container:
image: ${{ matrix.tag }}
steps:
Expand All @@ -65,7 +64,7 @@ jobs:
steps:
- uses: compnerd/gha-setup-swift@main
with:
branch: swift-5.10-release
tag: 5.10-RELEASE
branch: swift-6.0-release
tag: 6.0-RELEASE
- uses: actions/checkout@v4
- run: swift test
63 changes: 63 additions & 0 deletions .swift-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
"version" : 1,
"indentation" : {
"spaces" : 4
},
"tabWidth" : 4,
"fileScopedDeclarationPrivacy" : {
"accessLevel" : "private"
},
"spacesAroundRangeFormationOperators" : false,
"indentConditionalCompilationBlocks" : false,
"indentSwitchCaseLabels" : false,
"lineBreakAroundMultilineExpressionChainComponents" : false,
"lineBreakBeforeControlFlowKeywords" : false,
"lineBreakBeforeEachArgument" : true,
"lineBreakBeforeEachGenericRequirement" : true,
"lineLength" : 150,
"maximumBlankLines" : 1,
"respectsExistingLineBreaks" : true,
"prioritizeKeepingFunctionOutputTogether" : true,
"multiElementCollectionTrailingCommas" : true,
"rules" : {
"AllPublicDeclarationsHaveDocumentation" : false,
"AlwaysUseLiteralForEmptyCollectionInit" : false,
"AlwaysUseLowerCamelCase" : false,
"AmbiguousTrailingClosureOverload" : true,
"BeginDocumentationCommentWithOneLineSummary" : false,
"DoNotUseSemicolons" : true,
"DontRepeatTypeInStaticProperties" : true,
"FileScopedDeclarationPrivacy" : true,
"FullyIndirectEnum" : true,
"GroupNumericLiterals" : true,
"IdentifiersMustBeASCII" : true,
"NeverForceUnwrap" : false,
"NeverUseForceTry" : false,
"NeverUseImplicitlyUnwrappedOptionals" : false,
"NoAccessLevelOnExtensionDeclaration" : true,
"NoAssignmentInExpressions" : true,
"NoBlockComments" : true,
"NoCasesWithOnlyFallthrough" : true,
"NoEmptyTrailingClosureParentheses" : true,
"NoLabelsInCasePatterns" : true,
"NoLeadingUnderscores" : false,
"NoParensAroundConditions" : true,
"NoVoidReturnOnFunctionSignature" : true,
"OmitExplicitReturns" : true,
"OneCasePerLine" : true,
"OneVariableDeclarationPerLine" : true,
"OnlyOneTrailingClosureArgument" : true,
"OrderedImports" : true,
"ReplaceForEachWithForLoop" : true,
"ReturnVoidInsteadOfEmptyTuple" : true,
"UseEarlyExits" : false,
"UseExplicitNilCheckInConditions" : false,
"UseLetInEveryBoundCaseVariable" : false,
"UseShorthandTypeNames" : true,
"UseSingleLinePropertyGetter" : false,
"UseSynthesizedInitializer" : false,
"UseTripleSlashForDocumentationComments" : true,
"UseWhereClausesInForLoops" : false,
"ValidateDocumentationComments" : false
}
}
23 changes: 0 additions & 23 deletions .swiftformat

This file was deleted.

9 changes: 5 additions & 4 deletions Sources/JMESPath/Expression.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public struct JMESExpression: JMESSendable {
/// - Throws: JMESPathError
/// - Returns: Search result
public func search<Value>(json: Data, as: Value.Type = Value.self, runtime: JMESRuntime = .init()) throws -> Value? {
return try self.search(json: json, runtime: runtime) as? Value
try self.search(json: json, runtime: runtime) as? Value
}

/// Search JSON
Expand All @@ -35,7 +35,7 @@ public struct JMESExpression: JMESSendable {
/// - Throws: JMESPathError
/// - Returns: Search result
public func search<Value>(json: String, as: Value.Type = Value.self, runtime: JMESRuntime = .init()) throws -> Value? {
return try self.search(json: json, runtime: runtime) as? Value
try self.search(json: json, runtime: runtime) as? Value
}

/// Search Swift type
Expand All @@ -47,7 +47,8 @@ public struct JMESExpression: JMESSendable {
/// - Throws: JMESPathError
/// - Returns: Search result
public func search<Value>(object: Any, as: Value.Type = Value.self, runtime: JMESRuntime = .init()) throws -> Value? {
return try self.search(object: object, runtime: runtime) as? Value
let value = try self.search(object: object, runtime: runtime)
return value as? Value
}

/// Search JSON
Expand Down Expand Up @@ -82,7 +83,7 @@ public struct JMESExpression: JMESSendable {
/// - Throws: JMESPathError
/// - Returns: Search result
public func search(object: Any, runtime: JMESRuntime = .init()) throws -> Any? {
return try runtime.interpret(JMESVariable(from: object), ast: self.ast).collapse()
try runtime.interpret(JMESVariable(from: object), ast: self.ast).collapse()
}

private init(_ ast: Ast) {
Expand Down
76 changes: 42 additions & 34 deletions Sources/JMESPath/Functions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ public struct FunctionSignature {
/// - Parameter args: Array of arguments
/// - Throws: JMESPathError.runtime
func validateArgs(_ args: [JMESVariable]) throws {
guard args.count == self.inputs.count ||
(args.count > self.inputs.count && self.varArg != nil)
guard args.count == self.inputs.count || (args.count > self.inputs.count && self.varArg != nil)
else {
throw JMESPathError.runtime("Invalid number of arguments, expected \(self.inputs.count), got \(args.count)")
}
Expand All @@ -76,13 +75,13 @@ extension JMESVariable {
func isType(_ type: FunctionSignature.ArgumentType) -> Bool {
switch (self, type) {
case (_, .any),
(.string, .string),
(.null, .null),
(.number, .number),
(.boolean, .boolean),
(.array, .array),
(.object, .object),
(.expRef, .expRef):
(.string, .string),
(.null, .null),
(.number, .number),
(.boolean, .boolean),
(.array, .array),
(.object, .object),
(.expRef, .expRef):
return true

case (.array(let array), .typedArray(let elementType)):
Expand Down Expand Up @@ -128,7 +127,7 @@ public protocol JMESFunction {

/// Protocl for JMESPath function that takes a single number
protocol NumberFunction: JMESFunction {
static func evaluate(_ number: NSNumber) -> JMESVariable
static func evaluate(_ number: JMESNumber) -> JMESVariable
}

extension NumberFunction {
Expand Down Expand Up @@ -166,8 +165,8 @@ extension ArrayFunction {
/// Returns the absolute value of the provided argument. The signature indicates that a number is returned, and that the
/// input argument must resolve to a number, otherwise a invalid-type error is triggered.
struct AbsFunction: NumberFunction {
static func evaluate(_ number: NSNumber) -> JMESVariable {
return .number(.init(value: abs(number.doubleValue)))
static func evaluate(_ number: JMESNumber) -> JMESVariable {
.number(number.abs())
}
}

Expand All @@ -177,22 +176,22 @@ struct AvgFunction: ArrayFunction {
static var signature: FunctionSignature { .init(inputs: .typedArray(.number)) }
static func evaluate(_ array: JMESArray) -> JMESVariable {
guard array.count > 0 else { return .null }
let total = array.reduce(0.0) {
let total = array.reduce(JMESNumber(0)) {
if case .number(let number) = JMESVariable(from: $1) {
return $0 + number.doubleValue
return $0 + number
} else {
preconditionFailure()
}
}
return .number(.init(value: total / Double(array.count)))
return .number(total / JMESNumber(Double(array.count)))
}
}

/// `number ceil(number $value)`
/// Returns the next highest integer value by rounding up if necessary.
struct CeilFunction: NumberFunction {
static func evaluate(_ number: NSNumber) -> JMESVariable {
return .number(.init(value: ceil(number.doubleValue)))
static func evaluate(_ number: JMESNumber) -> JMESVariable {
.number(number.ceil())
}
}

Expand Down Expand Up @@ -236,8 +235,8 @@ struct EndsWithFunction: JMESFunction {
/// `number floor(number $value)`
/// Returns the next lowest integer value by rounding down if necessary.
struct FloorFunction: NumberFunction {
static func evaluate(_ number: NSNumber) -> JMESVariable {
return .number(.init(value: floor(number.doubleValue)))
static func evaluate(_ number: JMESNumber) -> JMESVariable {
.number(number.floor())
}
}

Expand Down Expand Up @@ -289,11 +288,11 @@ struct LengthFunction: JMESFunction {
static func evaluate(args: [JMESVariable], runtime: JMESRuntime) -> JMESVariable {
switch args[0] {
case .array(let array):
return .number(.init(value: array.count))
return .number(.init(array.count))
case .object(let object):
return .number(.init(value: object.count))
return .number(.init(object.count))
case .string(let string):
return .number(.init(value: string.count))
return .number(.init(string.count))
default:
preconditionFailure()
}
Expand Down Expand Up @@ -342,7 +341,7 @@ struct MaxFunction: JMESFunction {
case .number(var max):
for element in array.dropFirst() {
if case .number(let number) = JMESVariable(from: element) {
if number.compare(max) == .orderedDescending {
if number > max {
max = number
}
}
Expand Down Expand Up @@ -389,7 +388,7 @@ struct MaxByFunction: JMESFunction {
for element in array.dropFirst() {
let value = try runtime.interpret(JMESVariable(from: element), ast: ast)
if case .number(let number) = value {
if number.compare(maxValue) == .orderedDescending {
if number > maxValue {
maxValue = number
maxElement = element
}
Expand Down Expand Up @@ -430,7 +429,7 @@ struct MinFunction: JMESFunction {
case .number(var min):
for element in array {
if case .number(let number) = JMESVariable(from: element) {
if number.compare(min) == .orderedAscending {
if number < min {
min = number
}
}
Expand Down Expand Up @@ -477,7 +476,7 @@ struct MinByFunction: JMESFunction {
for element in array.dropFirst() {
let value = try runtime.interpret(JMESVariable(from: element), ast: ast)
if case .number(let number) = value {
if number.compare(minValue) == .orderedAscending {
if number < minValue {
minValue = number
minElement = element
}
Expand Down Expand Up @@ -603,7 +602,9 @@ struct SortByFunction: JMESFunction {
let restOfTheValues = try array.dropFirst().map { element -> ValueAndSortKey in
let sortValue = try runtime.interpret(JMESVariable(from: element), ast: ast)
guard sortValue.isSameType(as: firstSortValue) else {
throw JMESPathError.runtime("Sort arguments all have to be the same type, expected \(firstSortValue.getType()), instead got \(sortValue.getType())")
throw JMESPathError.runtime(
"Sort arguments all have to be the same type, expected \(firstSortValue.getType()), instead got \(sortValue.getType())"
)
}
return .init(value: element, sortValue: sortValue)
}
Expand Down Expand Up @@ -636,14 +637,21 @@ struct StartsWithFunction: JMESFunction {
struct SumFunction: ArrayFunction {
static var signature: FunctionSignature { .init(inputs: .typedArray(.number)) }
static func evaluate(_ array: JMESArray) -> JMESVariable {
let total = array.reduce(0.0) {
if case .number(let number) = JMESVariable(from: $1) {
return $0 + number.doubleValue
} else {
preconditionFailure()
guard let first = array.first.map({ JMESVariable(from: $0) }) else { return .number(.init(0)) }
switch first {
case .number(let number):
let total = array.dropFirst().reduce(number) {
if case .number(let number) = JMESVariable(from: $1) {
return $0 + number
} else {
preconditionFailure()
}
}
return .number(total)

default:
preconditionFailure()
}
return .number(.init(value: total))
}
}

Expand Down Expand Up @@ -709,7 +717,7 @@ struct ToStringFunction: JMESFunction {
struct TypeFunction: JMESFunction {
static var signature: FunctionSignature { .init(inputs: .any) }
static func evaluate(args: [JMESVariable], runtime: JMESRuntime) throws -> JMESVariable {
return .string(args[0].getType())
.string(args[0].getType())
}
}

Expand Down
4 changes: 1 addition & 3 deletions Sources/JMESPath/Lexer.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import Foundation

/// Lexer object
///
/// Parses raw text to create an array of tokens
Expand Down Expand Up @@ -216,6 +214,6 @@ internal class Lexer {
}

private func reachedEnd() -> Bool {
return self.index == self.text.endIndex
self.index == self.text.endIndex
}
}
Loading
Loading