LeafConfiguration Encoding and Formatting Options
Pre-releaseThis patch was authored and released by @tdotclare.
This release adds configuration methods for setting the default presentation output of data in rendered Leaf templates.
These options are all settable before LeafKit starts running.
Property Options
Stored property options in a LeafConfiguration may be used in various ways by a LeafRenderer which the configuration object was for, and changes to them after the object was provided to a specific LeafRenderer will have no affect.
.rootDirectory: String // The default file directory used for file-system based `LeafSource`s Static Options
Static options on LeafConfiguration are effectively constant once any LeafRenderer has been instantiated and attempts to change them will assert in Debug and silently fail in Release to prevent inconsistent behavior.
// The global tag indicator for LeafKit
.tagIndicator: Character == "#"
// Encoding used when a template is serialized
.encoding: String.Encoding == .utf8
// Formatters for converting the base internal data types to Strings for serialization
.boolFormatter: (Bool) -> String = { $0.description } // Bool.description
.intFormatter: (Int) -> String = { $0.description } // Int.description
.doubleFormatter: (Double) -> String = { $0.description } // Double.description
.nilFormatter: () -> String = { "" } // Empty string (Optional containing .none)
.voidFormatter: () -> String = { "" } // Empty string (Tag with no return value)
.stringFormatter: (String) -> String = { $0 } // Identity return
.dataFormatter: (Data) -> String? =
{ String(data: $0, encoding: Self._encoding) } // Data using .encoding
// Note: Array & Dictionaries elements will already have been converted to Strings
.arrayFormatter: ([String]) -> String = // Array: [element, ..., element]
{ "[\($0.map {"\"\($0)\""}.joined(separator: ", "))]" }
.dictFormatter: ([String: String]) -> String = // Dictionary: [key: value, ..., key: value]
{ "[\($0.map { "\($0): \"\($1)\"" }.joined(separator: ", "))]" }API Changes
-
Character.tagIndicatorcan no longer be directly set - it must be configured throughLeafConfiguration -
LeafData.NaturalTyperepresents eight concrete Swift data types Leaf handles:- Instantiable data types: [Bool, Int, Double, String, Array, Dictionary, Data]
- Non-instantiable: [Void]
-
LeafDatastatic initializers from Swift data types now take Optional values:- If input is
.none, the returnedLeafDatarepresents aOptional.nonestate of the specific type .nilstatic initializer now requires a concrete type fromLeafData.NaturalTypebe specified
- If input is
-
LeafDataobjects present the following informational states:celf: NaturalType of the objectisNil: whether the object contains.noneisCollection: if the object's type isarrayordictionary.isCastable(to type: NaturalType): whether the type is implicitly castable to a second typeisCoercible(to type: NaturalType): whether the type has an implicit one-way conersion path to the second type- NOTE both above methods are inherently true when the two types are the same type, or castable when asking if coercible.
hasUniformType: whether the object consists of one concrete type (true for all non-containers), false if it can be determined that it does not, and nil in unusual cases where an object is storing an internal dynamic data generator that returns a container itself.uniformType: If the object can be determined to have auniformType, returns that type or nil if not determinable.
-
LeafDataRepresentableadherence now requires.leafDatareturnLeafDatarather thanLeafData?- Updated static initalizers mentioned above will automatically handle creating
LeafDataholding.nonewhere otherwise a nil return would occur - Generic conformances for various Swift base types are updated to reflect this:
-
let invalidValue: Float80 = Float80.max let leafData = invalidValue.leafData // leafData now represents the equivalent of Double? containing nil
- Default implementations for protocols
FixedWidthIntegerandBinaryFloatingPoint - Adherance via above for
Bool,String,Int/Int8/Int32/Int64/UInt/UInt8/UInt16/UInt32/UInt64,Float/Double/Float80,Data,UUID(via String),Date(via Double),Array<LeafDataRepresentable>,Dictionary<String, LeafDataRepresentable>,Set<LeafDataRepresentable>via Array
-
- Updated static initalizers mentioned above will automatically handle creating
Internal Only
Substantial internal changes to LeafData, LeafDataRepresentable Protocol, LeafDataStorage :
LeafDataconversion between types is now explicitly handled bycastableandcoerciblerules where underlying types are different. The default behaviors allow only implicit conversion viacastablerules where a clearly established bi-directional rule exists between the two types.LeafDataStoragesignifcantly modified to allow above behaviors- Internal
Lazyresolvable data generators must now state their concrete return type and whether they have variant return behavior; such generators will never be tested in any kind of comparison states to prevent side-effects - they will only be called when a template serializes. - Various state evaluation, data conversion, and related behaviors are moved internally to the enum definition to prevent confusing situations
- Internal
- Various internal changes reflecting the above modifications
Fixes
- Throws an error if overflowing add/subtract on integer values