Skip to content

Commit ee2667a

Browse files
committed
New library (lispkit url). Lots of small tweaks to several libraries.
1 parent 68b31c4 commit ee2667a

File tree

12 files changed

+800
-239
lines changed

12 files changed

+800
-239
lines changed

LispKit.xcodeproj/project.pbxproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,8 @@
567567
CC882C921C9E93A600D20039 /* Timer.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC882C911C9E93A600D20039 /* Timer.swift */; };
568568
CC894F202CC3022800896B1D /* PasteboardLibrary.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC894F1F2CC3022800896B1D /* PasteboardLibrary.swift */; };
569569
CC894F242CC3B08100896B1D /* PasteboardLibrary_iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC894F222CC3B08100896B1D /* PasteboardLibrary_iOS.swift */; };
570+
CC894F262CCD0AAC00896B1D /* URLLibrary.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC894F252CCD0AAC00896B1D /* URLLibrary.swift */; };
571+
CC894F272CCD0AAC00896B1D /* URLLibrary.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC894F252CCD0AAC00896B1D /* URLLibrary.swift */; };
570572
CC8A2AAF1F405E2500D1E4D8 /* 17.sld in Copy pre-installed SRFI libraries */ = {isa = PBXBuildFile; fileRef = CC8A2AAE1F405CDD00D1E4D8 /* 17.sld */; };
571573
CC8A2AB11F40681500D1E4D8 /* 48.sld in Copy pre-installed SRFI libraries */ = {isa = PBXBuildFile; fileRef = CC8A2AB01F40672700D1E4D8 /* 48.sld */; };
572574
CC8BBA2A26BF3B1A00552B8F /* text-table.sld in Copy pre-installed LispKit libraries */ = {isa = PBXBuildFile; fileRef = CC8BBA2926BF38F200552B8F /* text-table.sld */; };
@@ -3490,6 +3492,7 @@
34903492
CC882C911C9E93A600D20039 /* Timer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Timer.swift; sourceTree = "<group>"; };
34913493
CC894F1F2CC3022800896B1D /* PasteboardLibrary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasteboardLibrary.swift; sourceTree = "<group>"; };
34923494
CC894F222CC3B08100896B1D /* PasteboardLibrary_iOS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasteboardLibrary_iOS.swift; sourceTree = "<group>"; };
3495+
CC894F252CCD0AAC00896B1D /* URLLibrary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLLibrary.swift; sourceTree = "<group>"; };
34933496
CC8A2AAE1F405CDD00D1E4D8 /* 17.sld */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = 17.sld; sourceTree = "<group>"; };
34943497
CC8A2AB01F40672700D1E4D8 /* 48.sld */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = 48.sld; sourceTree = "<group>"; };
34953498
CC8BBA2926BF38F200552B8F /* text-table.sld */ = {isa = PBXFileReference; lastKnownFileType = text; path = "text-table.sld"; sourceTree = "<group>"; };
@@ -4766,6 +4769,7 @@
47664769
CC2DA7462773195600DE69CF /* ThreadLibrary.swift */,
47674770
CCD5B6072C276696002BF2F0 /* ThreadFutureLibrary.swift */,
47684771
CCCCEC8C2C50520600509902 /* SharedQueueLibrary.swift */,
4772+
CC894F252CCD0AAC00896B1D /* URLLibrary.swift */,
47694773
CCD5B60A2C295951002BF2F0 /* HTTPLibrary.swift */,
47704774
CCCCEC892C504B3C00509902 /* HTTPServerLibrary.swift */,
47714775
CCD5B6152C3BC480002BF2F0 /* HTTPOAuthLibrary.swift */,
@@ -5566,6 +5570,7 @@
55665570
CCCB66E4283056E30004827D /* StyledTextLibrary.swift in Sources */,
55675571
CC6A3B6A1C539DCA00E962E2 /* ManagedObjectPool.swift in Sources */,
55685572
CC7D4B7E2A2A49B50066BA94 /* Formatter.swift in Sources */,
5573+
CC894F262CCD0AAC00896B1D /* URLLibrary.swift in Sources */,
55695574
CCC62D921CA9ED6A00E2C43F /* TrackedObject.swift in Sources */,
55705575
CC38528B23126F7A001D5E56 /* InternalLibrary.swift in Sources */,
55715576
CC2DA7472773195600DE69CF /* ThreadLibrary.swift in Sources */,
@@ -5628,6 +5633,7 @@
56285633
CCC48CD825E5B98600D082AD /* PortLibrary.swift in Sources */,
56295634
CCD5E5822631F51700C45EA0 /* Drawing_iOS.swift in Sources */,
56305635
CCC48CC325E5B98600D082AD /* VectorLibrary.swift in Sources */,
5636+
CC894F272CCD0AAC00896B1D /* URLLibrary.swift in Sources */,
56315637
CCC48C7025E5B94300D082AD /* Reference.swift in Sources */,
56325638
CCC48CAC25E5B97100D082AD /* NativeLibrary.swift in Sources */,
56335639
CCC48CBD25E5B98600D082AD /* CharLibrary.swift in Sources */,

Sources/LispKit/Compiler/EvalError.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,9 @@ public enum EvalError: Int, Hashable, Codable {
190190
case illegalPolicySpecifier
191191
case unsupportedBarcodeSetting
192192
case oauthError
193+
case urlFormatConstraintError
194+
case urlAuthorityError
195+
case urlPrototypeInvalid
193196

194197
public var message: String {
195198
switch self {
@@ -523,6 +526,12 @@ public enum EvalError: Int, Hashable, Codable {
523526
return "unsupported barcode setting key: $0"
524527
case .oauthError:
525528
return "oauth2 error $0: $,1"
529+
case .urlFormatConstraintError:
530+
return "not a valid URL format constraint: $0"
531+
case .urlAuthorityError:
532+
return "invalid URL authority specifier: $0"
533+
case .urlPrototypeInvalid:
534+
return "$0 is not a valid URL prototype for procedure $,1"
526535
}
527536
}
528537

Sources/LispKit/Data/Type.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ public enum Type: Hashable, CustomStringConvertible {
7070
case binaryOutputPortType
7171
case taggedType
7272
case syntaxType
73+
case urlType
7374
case objectType(Symbol)
7475

7576
public var description: String {
@@ -170,13 +171,17 @@ public enum Type: Hashable, CustomStringConvertible {
170171
return "tagged"
171172
case .syntaxType:
172173
return "syntax"
174+
case .urlType:
175+
return "url"
173176
case .objectType(let sym):
174177
return sym.identifier
175178
}
176179
}
177180

178181
public var included: Set<Type> {
179182
switch self {
183+
case .strType:
184+
return stringSubtypes
180185
case .procedureType:
181186
return procedureSubtypes
182187
case .numberType:
@@ -220,6 +225,8 @@ public enum Type: Hashable, CustomStringConvertible {
220225
}
221226
}
222227

228+
private let stringSubtypes : Set<Type> = [.strType,
229+
.urlType]
223230
private let procedureSubtypes : Set<Type> = [.procedureType,
224231
.parameterType]
225232
private let numberSubtypes : Set<Type> = [.numberType,

Sources/LispKit/Primitives/ControlFlowLibrary.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public final class ControlFlowLibrary: NativeLibrary {
5555
self.define(SpecialForm("unless", self.compileUnless))
5656
self.define(SpecialForm("cond", self.compileCond))
5757
self.define(SpecialForm("case", self.compileCase))
58-
self.define("if-let*-inner", via: """
58+
self.define("if-let*-inner", export: false, via: """
5959
(define-syntax if-let*-inner
6060
(syntax-rules ()
6161
((_ ((var expr) . clauses) body)

Sources/LispKit/Primitives/DrawBarcodeLibrary.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ public final class DrawBarcodeLibrary: NativeLibrary {
156156
private func aztecCodeImage(str: Expr, args: Arguments) throws -> Expr {
157157
guard let (corr, compact, scale, color, background, dpi) = args.optional(.flonum(23.0),
158158
.null,
159-
.flonum(1.0),
159+
.flonum(2.0),
160160
.false,
161161
.false,
162162
.flonum(72.0)) else {

Sources/LispKit/Primitives/HTTPServerLibrary.swift

Lines changed: 118 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@
2121
import Foundation
2222
import NanoHTTP
2323
import DynamicJSON
24+
#if os(iOS) || os(watchOS) || os(tvOS)
25+
import UIKit
26+
#elseif os(macOS)
27+
import Cocoa
28+
#endif
2429

2530
public final class HTTPServerLibrary: NativeLibrary {
2631

@@ -69,6 +74,7 @@ public final class HTTPServerLibrary: NativeLibrary {
6974
self.define(Procedure("make-http-server", self.makeHttpServer))
7075
self.define(Procedure("http-server-running?", self.isHttpServerRunning))
7176
self.define(Procedure("http-server-port", self.httpServerPort))
77+
self.define(Procedure("http-server-ipv4", self.isHttpServerIPv4))
7278
self.define(Procedure("http-server-open-connections", self.httpServerOpenConnections))
7379
self.define(Procedure("http-server-routes", self.httpServerRoutes))
7480
self.define(Procedure("http-server-handlers", self.httpServerHandlers))
@@ -107,12 +113,12 @@ public final class HTTPServerLibrary: NativeLibrary {
107113
self.define(Procedure("srv-request-form-attributes", self.serverRequestFormAttributes))
108114
self.define(Procedure("srv-request-form-multiparts", self.serverRequestFormMultiparts))
109115
self.define(Procedure("srv-request-address", self.serverRequestAddress))
110-
self.define(Procedure("srv-request-address", self.serverRequestAddress))
111116
self.define(Procedure("_srv-request-send-response", self.serverRequestSendResponse), export: false)
112117
self.define(Procedure("srv-multipart?", self.isServerMultipart))
113118
self.define(Procedure("srv-multipart-headers", self.serverMultipartHeaders))
114119
self.define(Procedure("srv-multipart-header", self.serverMultipartHeader))
115120
self.define(Procedure("srv-multipart-body", self.serverMultipartBody))
121+
self.define(Procedure("srv-multipart-body->string", self.serverMultipartBodyToString))
116122
self.define(Procedure("srv-response?", self.isSrvResponse))
117123
self.define(Procedure("_make-srv-response", self.makeSrvResponse), export: false)
118124
self.define(Procedure("srv-response-created", self.srvResponseCreated))
@@ -377,7 +383,9 @@ public final class HTTPServerLibrary: NativeLibrary {
377383
private func httpServerRegister(expr: Expr, fst: Expr, snd: Expr, thd: Expr?) throws -> Expr {
378384
if let handler = thd {
379385
_ = try handler.asProcedure()
380-
try self.httpServer(from: expr).register(method: try fst.asString().uppercased(),
386+
try self.httpServer(from: expr).register(method: fst.isFalse
387+
? nil
388+
: try fst.asString().uppercased(),
381389
path: try snd.asString(),
382390
handler: handler)
383391
} else {
@@ -483,17 +491,31 @@ public final class HTTPServerLibrary: NativeLibrary {
483491
return .makeString(try self.httpServerRequest(from: expr).connection.request.path)
484492
}
485493

486-
private func serverRequestQuery(expr: Expr) throws -> Expr {
494+
private func serverRequestQuery(expr: Expr, inclPath: Expr?) throws -> Expr {
487495
let req = try self.httpServerRequest(from: expr)
488496
var components = URLComponents()
489-
components.path = req.connection.request.path
490-
if !req.connection.request.queryParams.isEmpty {
497+
if req.connection.request.queryParams.isEmpty {
498+
if inclPath?.isTrue ?? false {
499+
components.path = req.connection.request.path
500+
} else {
501+
return .makeString("")
502+
}
503+
} else {
504+
if inclPath?.isTrue ?? false {
505+
components.path = req.connection.request.path
506+
}
491507
components.queryItems = req.connection.request.queryParams.map { k, v in
492508
return URLQueryItem(name: k.removingPercentEncoding ?? k,
493509
value: v.removingPercentEncoding ?? v)
494510
}
495511
}
496-
return .makeString(components.url?.absoluteString ?? req.connection.request.path)
512+
if let str = components.string {
513+
return .makeString(str)
514+
} else if inclPath?.isTrue ?? false {
515+
return .makeString(req.connection.request.path)
516+
} else {
517+
return .makeString("")
518+
}
497519
}
498520

499521
private func serverRequestPathParam(expr: Expr, name: Expr, default: Expr?) throws -> Expr {
@@ -662,6 +684,14 @@ public final class HTTPServerLibrary: NativeLibrary {
662684
return .bytes(MutableBox(try self.multiPart(from: expr).multipart.body))
663685
}
664686

687+
private func serverMultipartBodyToString(expr: Expr) throws -> Expr {
688+
guard let str = String(bytes: try self.multiPart(from: expr).multipart.body,
689+
encoding: .utf8) else {
690+
return .false
691+
}
692+
return .makeString(str)
693+
}
694+
665695
// HTTP server response functionality
666696

667697
private func isSrvResponse(expr: Expr) -> Expr {
@@ -770,12 +800,72 @@ public final class HTTPServerLibrary: NativeLibrary {
770800
return .void
771801
}
772802

803+
#if os(iOS) || os(watchOS) || os(tvOS)
804+
private func image(_ image: NativeImage, to mimeType: String) -> Data? {
805+
var type: BitmapImageFileType
806+
switch mimeType {
807+
case "image/tiff":
808+
type = .tiff
809+
case "image/png":
810+
type = .png
811+
case "image/jpeg":
812+
type = .jpeg
813+
case "image/gif":
814+
type = .gif
815+
case "image/bmp":
816+
type = .bmp
817+
default:
818+
return nil
819+
}
820+
return type.data(for: image.value)
821+
}
822+
#elseif os(macOS)
823+
private func image(_ image: NativeImage, to mimeType: String) -> Data? {
824+
var type: NSBitmapImageRep.FileType
825+
switch mimeType {
826+
case "image/tiff":
827+
type = .tiff
828+
case "image/png":
829+
type = .png
830+
case "image/jpeg":
831+
type = .jpeg
832+
case "image/gif":
833+
type = .gif
834+
case "image/bmp":
835+
type = .bmp
836+
default:
837+
return nil
838+
}
839+
for repr in image.value.representations {
840+
if let bitmapRepr = repr as? NSBitmapImageRep {
841+
return bitmapRepr.representation(using: type, properties: [:])
842+
}
843+
}
844+
return nil
845+
}
846+
#endif
847+
773848
private func srvResponseBody(from obj: Expr, contentType: Expr?) throws -> NanoHTTPResponse.Body {
774849
switch obj {
775850
case .false:
776851
return .empty
777-
case .string(_):
778-
return .text(try obj.asString())
852+
case .string(let str):
853+
if let ct = try contentType?.asString() {
854+
switch ct {
855+
case "text/plain":
856+
return .text(str as String)
857+
case "text/html":
858+
return .html(str as String)
859+
default:
860+
if let data = (str as String).data(using: .utf8) {
861+
return .data(data, contentType: ct)
862+
} else {
863+
return .text(str as String)
864+
}
865+
}
866+
} else {
867+
return .text(str as String)
868+
}
779869
case .bytes(let bv):
780870
return .data(Data(bv.value), contentType: try contentType?.asString())
781871
case .object(let obj):
@@ -784,15 +874,28 @@ public final class HTTPServerLibrary: NativeLibrary {
784874
} else if let mutable = obj as? MutableJSON {
785875
return .json(mutable.value)
786876
} else if let str = obj as? StyledText {
877+
if contentType?.isTrue ?? false {
878+
let data = try str.value.data(
879+
from: NSMakeRange(0, str.value.length),
880+
documentAttributes: [.documentType : NSAttributedString.DocumentType.rtf])
881+
return .data(data, contentType: "application/rtf")
882+
}
787883
let data = try str.value.data(
788-
from: NSRange(location: 0, length: str.value.length),
789-
documentAttributes:[.documentType: NSAttributedString.DocumentType.html,
790-
.characterEncoding: String.Encoding.utf8.rawValue])
884+
from: NSRange(location: 0, length: str.value.length),
885+
documentAttributes:[.documentType: NSAttributedString.DocumentType.html,
886+
.characterEncoding: String.Encoding.utf8.rawValue])
791887
if let res = String(data: data, encoding: String.Encoding.utf8) {
792888
return .htmlBody(res)
793889
} else {
794890
fallthrough
795891
}
892+
} else if let image = obj as? NativeImage {
893+
let ct = try contentType?.asString() ?? "image/png"
894+
if let data = self.image(image, to: ct) {
895+
return .data(data, contentType: ct)
896+
} else {
897+
fallthrough
898+
}
796899
} else {
797900
fallthrough
798901
}
@@ -824,7 +927,8 @@ public final class HTTPServerLibrary: NativeLibrary {
824927
let name = try name.asString().lowercased()
825928
var list = expr
826929
while case .pair(let element, let next) = list {
827-
if case .pair(.string(let str), let value) = element, (str as String) == name {
930+
if case .pair(.string(let str), let value) = element,
931+
(str as String).lowercased() == name {
828932
return value
829933
}
830934
list = next
@@ -851,6 +955,8 @@ public final class HTTPServerLibrary: NativeLibrary {
851955
}
852956
current = value.index(after: current)
853957
start = current
958+
} else {
959+
fallthrough
854960
}
855961
default:
856962
current = value.index(after: current)

Sources/LispKit/Primitives/LibraryRegistry.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ public struct LibraryRegistry {
6666
ThreadLibrary.self,
6767
ThreadFutureLibrary.self,
6868
SharedQueueLibrary.self,
69+
URLLibrary.self,
6970
JSONLibrary.self,
7071
JSONSchemaLibrary.self,
7172
HTTPLibrary.self,
@@ -114,6 +115,7 @@ public struct LibraryRegistry {
114115
ThreadLibrary.self,
115116
ThreadFutureLibrary.self,
116117
SharedQueueLibrary.self,
118+
URLLibrary.self,
117119
JSONLibrary.self,
118120
JSONSchemaLibrary.self,
119121
HTTPLibrary.self,

0 commit comments

Comments
 (0)