This is an automated email from the ASF dual-hosted git repository.

chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory.git


The following commit(s) were added to refs/heads/main by this push:
     new 6117f5d0b feat(swift): support enum/time serialization for swift 
(#3371)
6117f5d0b is described below

commit 6117f5d0b38ba38b298020d43f2282f9a7e347b3
Author: Shawn Yang <[email protected]>
AuthorDate: Thu Feb 19 22:09:36 2026 +0800

    feat(swift): support enum/time serialization for swift (#3371)
    
    ## Why?
    
    - Align Swift package/module naming with the rest of the project
    (`ForySwift` -> `Fory`) and simplify target layout.
    - Add missing built-in xlang date/time support and macro-generated enum
    serialization support.
    - Increase Swift test coverage for these features and for weak-reference
    tracking behavior.
    
    
    ## What does this PR do?
    
    - Renames Swift package products/targets and source directories:
      - `ForySwift` -> `Fory`
      - `ForySwiftMacros` -> `ForyMacro`
      - `ForySwiftTests` -> `ForyTests`
      - Moves xlang peer target to `Tests/ForyXlangPeer`
    - Adds `DateTimeSerializers.swift` with:
      - `ForyDate` (`.date`)
      - `ForyTimestamp` (`.timestamp`, with second/nanos normalization)
      - `Date: Serializer` bridge using timestamp encoding
    - Wires date/time support into deserialization paths (`TypeResolver` and
    `FieldSkipper`).
    - Updates `Context` helper dispatch to call module-global read/write
    helpers instead of `ForySwift.*` symbols.
    - Extends `@ForyObject` macro to support enums:
    - no-payload enums -> ordinal enum serialization (`ForyTypeId.enumType`)
    - associated-value enums -> tagged-union serialization
    (`ForyTypeId.typedUnion`)
    - Simplifies `ForyXlangPeer` by replacing handwritten enum/date/union
    serializers with macro-based enums and shared `ForyDate`/`ForyTimestamp`
    types.
    - Adds/updates tests:
    - `DateTimeTests.swift` for date/timestamp type IDs and round-trip
    behavior
      - `EnumTests.swift` for enum and tagged-union round trips
      - `ForySwiftTests.swift` coverage for weak self-reference tracking
    
    
    ## Related issues
    
    #1017
    #3349
    
    ## Does this PR introduce any user-facing change?
    
    
    
    - [x] Does this PR introduce any public API change?
    - [ ] Does this PR introduce any binary protocol compatibility change?
    
    ## Benchmark
---
 swift/Package.swift                                |  22 +-
 .../{ForySwift => Fory}/AnySerializer.swift        |   0
 swift/Sources/{ForySwift => Fory}/ByteBuffer.swift |   0
 .../CollectionSerializers.swift                    |   0
 swift/Sources/{ForySwift => Fory}/Context.swift    | 136 ++++++++++-
 swift/Sources/Fory/DateTimeSerializers.swift       | 117 ++++++++++
 .../Sources/{ForySwift => Fory}/FieldSkipper.swift |   8 +
 swift/Sources/{ForySwift => Fory}/Fory.swift       |   0
 swift/Sources/{ForySwift => Fory}/ForyError.swift  |   0
 swift/Sources/{ForySwift => Fory}/ForyFlags.swift  |   0
 swift/Sources/{ForySwift => Fory}/ForyTypeId.swift |   0
 .../{ForySwift => Fory}/MacroDeclarations.swift    |   4 +-
 swift/Sources/{ForySwift => Fory}/MetaString.swift |   0
 .../Sources/{ForySwift => Fory}/MurmurHash3.swift  |   0
 .../{ForySwift => Fory}/OptionalSerializer.swift   |   0
 .../{ForySwift => Fory}/PrimitiveSerializers.swift |   0
 .../Sources/{ForySwift => Fory}/RefResolver.swift  |   0
 swift/Sources/{ForySwift => Fory}/SchemaHash.swift |   0
 swift/Sources/{ForySwift => Fory}/Serializer.swift |   0
 swift/Sources/{ForySwift => Fory}/TypeMeta.swift   |   0
 .../Sources/{ForySwift => Fory}/TypeResolver.swift |   4 +
 .../ForyObjectMacro.swift                          | 252 +++++++++++++++++++++
 swift/Tests/ForyTests/DateTimeTests.swift          |  75 ++++++
 swift/Tests/ForyTests/EnumTests.swift              | 120 ++++++++++
 .../ForySwiftTests.swift                           |  30 ++-
 .../ForyXlangPeer}/main.swift                      | 141 ++----------
 26 files changed, 767 insertions(+), 142 deletions(-)

diff --git a/swift/Package.swift b/swift/Package.swift
index f787a0b56..f8a929d2c 100644
--- a/swift/Package.swift
+++ b/swift/Package.swift
@@ -10,8 +10,8 @@ let package = Package(
     ],
     products: [
         .library(
-            name: "ForySwift",
-            targets: ["ForySwift"]
+            name: "Fory",
+            targets: ["Fory"]
         ),
         .executable(
             name: "ForySwiftXlangPeer",
@@ -23,25 +23,29 @@ let package = Package(
     ],
     targets: [
         .macro(
-            name: "ForySwiftMacros",
+            name: "ForyMacro",
             dependencies: [
                 .product(name: "SwiftCompilerPlugin", package: "swift-syntax"),
                 .product(name: "SwiftSyntax", package: "swift-syntax"),
                 .product(name: "SwiftSyntaxBuilder", package: "swift-syntax"),
                 .product(name: "SwiftSyntaxMacros", package: "swift-syntax"),
-            ]
+            ],
+            path: "Sources/ForyMacro"
         ),
         .target(
-            name: "ForySwift",
-            dependencies: ["ForySwiftMacros"]
+            name: "Fory",
+            dependencies: ["ForyMacro"],
+            path: "Sources/Fory"
         ),
         .executableTarget(
             name: "ForySwiftXlangPeer",
-            dependencies: ["ForySwift"]
+            dependencies: ["Fory"],
+            path: "Tests/ForyXlangPeer"
         ),
         .testTarget(
-            name: "ForySwiftTests",
-            dependencies: ["ForySwift"]
+            name: "ForyTests",
+            dependencies: ["Fory"],
+            path: "Tests/ForyTests"
         ),
     ]
 )
diff --git a/swift/Sources/ForySwift/AnySerializer.swift 
b/swift/Sources/Fory/AnySerializer.swift
similarity index 100%
rename from swift/Sources/ForySwift/AnySerializer.swift
rename to swift/Sources/Fory/AnySerializer.swift
diff --git a/swift/Sources/ForySwift/ByteBuffer.swift 
b/swift/Sources/Fory/ByteBuffer.swift
similarity index 100%
rename from swift/Sources/ForySwift/ByteBuffer.swift
rename to swift/Sources/Fory/ByteBuffer.swift
diff --git a/swift/Sources/ForySwift/CollectionSerializers.swift 
b/swift/Sources/Fory/CollectionSerializers.swift
similarity index 100%
rename from swift/Sources/ForySwift/CollectionSerializers.swift
rename to swift/Sources/Fory/CollectionSerializers.swift
diff --git a/swift/Sources/ForySwift/Context.swift 
b/swift/Sources/Fory/Context.swift
similarity index 83%
rename from swift/Sources/ForySwift/Context.swift
rename to swift/Sources/Fory/Context.swift
index c7aefa8ad..25285077b 100644
--- a/swift/Sources/ForySwift/Context.swift
+++ b/swift/Sources/Fory/Context.swift
@@ -372,6 +372,126 @@ public final class ReadContext {
     }
 }
 
+@inline(__always)
+private func writeAnyGlobal(
+    _ value: Any?,
+    context: WriteContext,
+    refMode: RefMode,
+    writeTypeInfo: Bool,
+    hasGenerics: Bool
+) throws {
+    try writeAny(
+        value,
+        context: context,
+        refMode: refMode,
+        writeTypeInfo: writeTypeInfo,
+        hasGenerics: hasGenerics
+    )
+}
+
+@inline(__always)
+private func writeAnyListGlobal(
+    _ value: [Any]?,
+    context: WriteContext,
+    refMode: RefMode,
+    writeTypeInfo: Bool,
+    hasGenerics: Bool
+) throws {
+    try writeAnyList(
+        value,
+        context: context,
+        refMode: refMode,
+        writeTypeInfo: writeTypeInfo,
+        hasGenerics: hasGenerics
+    )
+}
+
+@inline(__always)
+private func writeStringAnyMapGlobal(
+    _ value: [String: Any]?,
+    context: WriteContext,
+    refMode: RefMode,
+    writeTypeInfo: Bool,
+    hasGenerics: Bool
+) throws {
+    try writeStringAnyMap(
+        value,
+        context: context,
+        refMode: refMode,
+        writeTypeInfo: writeTypeInfo,
+        hasGenerics: hasGenerics
+    )
+}
+
+@inline(__always)
+private func writeInt32AnyMapGlobal(
+    _ value: [Int32: Any]?,
+    context: WriteContext,
+    refMode: RefMode,
+    writeTypeInfo: Bool,
+    hasGenerics: Bool
+) throws {
+    try writeInt32AnyMap(
+        value,
+        context: context,
+        refMode: refMode,
+        writeTypeInfo: writeTypeInfo,
+        hasGenerics: hasGenerics
+    )
+}
+
+@inline(__always)
+private func readAnyGlobal(
+    context: ReadContext,
+    refMode: RefMode,
+    readTypeInfo: Bool
+) throws -> Any? {
+    try readAny(
+        context: context,
+        refMode: refMode,
+        readTypeInfo: readTypeInfo
+    )
+}
+
+@inline(__always)
+private func readAnyListGlobal(
+    context: ReadContext,
+    refMode: RefMode,
+    readTypeInfo: Bool
+) throws -> [Any]? {
+    try readAnyList(
+        context: context,
+        refMode: refMode,
+        readTypeInfo: readTypeInfo
+    )
+}
+
+@inline(__always)
+private func readStringAnyMapGlobal(
+    context: ReadContext,
+    refMode: RefMode,
+    readTypeInfo: Bool
+) throws -> [String: Any]? {
+    try readStringAnyMap(
+        context: context,
+        refMode: refMode,
+        readTypeInfo: readTypeInfo
+    )
+}
+
+@inline(__always)
+private func readInt32AnyMapGlobal(
+    context: ReadContext,
+    refMode: RefMode,
+    readTypeInfo: Bool
+) throws -> [Int32: Any]? {
+    try readInt32AnyMap(
+        context: context,
+        refMode: refMode,
+        readTypeInfo: readTypeInfo
+    )
+}
+
 public extension WriteContext {
     func writeAny(
         _ value: Any?,
@@ -379,7 +499,7 @@ public extension WriteContext {
         writeTypeInfo: Bool = true,
         hasGenerics: Bool = false
     ) throws {
-        try ForySwift.writeAny(
+        try writeAnyGlobal(
             value,
             context: self,
             refMode: refMode,
@@ -394,7 +514,7 @@ public extension WriteContext {
         writeTypeInfo: Bool = false,
         hasGenerics: Bool = true
     ) throws {
-        try ForySwift.writeAnyList(
+        try writeAnyListGlobal(
             value,
             context: self,
             refMode: refMode,
@@ -409,7 +529,7 @@ public extension WriteContext {
         writeTypeInfo: Bool = false,
         hasGenerics: Bool = true
     ) throws {
-        try ForySwift.writeStringAnyMap(
+        try writeStringAnyMapGlobal(
             value,
             context: self,
             refMode: refMode,
@@ -424,7 +544,7 @@ public extension WriteContext {
         writeTypeInfo: Bool = false,
         hasGenerics: Bool = true
     ) throws {
-        try ForySwift.writeInt32AnyMap(
+        try writeInt32AnyMapGlobal(
             value,
             context: self,
             refMode: refMode,
@@ -439,7 +559,7 @@ public extension ReadContext {
         refMode: RefMode,
         readTypeInfo: Bool = true
     ) throws -> Any? {
-        try ForySwift.readAny(
+        try readAnyGlobal(
             context: self,
             refMode: refMode,
             readTypeInfo: readTypeInfo
@@ -450,7 +570,7 @@ public extension ReadContext {
         refMode: RefMode,
         readTypeInfo: Bool = false
     ) throws -> [Any]? {
-        try ForySwift.readAnyList(
+        try readAnyListGlobal(
             context: self,
             refMode: refMode,
             readTypeInfo: readTypeInfo
@@ -461,7 +581,7 @@ public extension ReadContext {
         refMode: RefMode,
         readTypeInfo: Bool = false
     ) throws -> [String: Any]? {
-        try ForySwift.readStringAnyMap(
+        try readStringAnyMapGlobal(
             context: self,
             refMode: refMode,
             readTypeInfo: readTypeInfo
@@ -472,7 +592,7 @@ public extension ReadContext {
         refMode: RefMode,
         readTypeInfo: Bool = false
     ) throws -> [Int32: Any]? {
-        try ForySwift.readInt32AnyMap(
+        try readInt32AnyMapGlobal(
             context: self,
             refMode: refMode,
             readTypeInfo: readTypeInfo
diff --git a/swift/Sources/Fory/DateTimeSerializers.swift 
b/swift/Sources/Fory/DateTimeSerializers.swift
new file mode 100644
index 000000000..9d0b2b704
--- /dev/null
+++ b/swift/Sources/Fory/DateTimeSerializers.swift
@@ -0,0 +1,117 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+import Foundation
+
+public struct ForyDate: Serializer, Equatable, Hashable {
+    public var daysSinceEpoch: Int32
+
+    public init(daysSinceEpoch: Int32 = 0) {
+        self.daysSinceEpoch = daysSinceEpoch
+    }
+
+    public static func foryDefault() -> ForyDate {
+        .init()
+    }
+
+    public static var staticTypeId: ForyTypeId {
+        .date
+    }
+
+    public func foryWriteData(_ context: WriteContext, hasGenerics: Bool) 
throws {
+        _ = hasGenerics
+        context.writer.writeInt32(daysSinceEpoch)
+    }
+
+    public static func foryReadData(_ context: ReadContext) throws -> ForyDate 
{
+        .init(daysSinceEpoch: try context.reader.readInt32())
+    }
+}
+
+public struct ForyTimestamp: Serializer, Equatable, Hashable {
+    public var seconds: Int64
+    public var nanos: UInt32
+
+    public init(seconds: Int64 = 0, nanos: UInt32 = 0) {
+        let normalized = Self.normalize(seconds: seconds, nanos: Int64(nanos))
+        self.seconds = normalized.seconds
+        self.nanos = normalized.nanos
+    }
+
+    public static func foryDefault() -> ForyTimestamp {
+        .init()
+    }
+
+    public static var staticTypeId: ForyTypeId {
+        .timestamp
+    }
+
+    public func foryWriteData(_ context: WriteContext, hasGenerics: Bool) 
throws {
+        _ = hasGenerics
+        context.writer.writeInt64(seconds)
+        context.writer.writeUInt32(nanos)
+    }
+
+    public static func foryReadData(_ context: ReadContext) throws -> 
ForyTimestamp {
+        .init(seconds: try context.reader.readInt64(), nanos: try 
context.reader.readUInt32())
+    }
+
+    public init(date: Date) {
+        let time = date.timeIntervalSince1970
+        let seconds = Int64(floor(time))
+        let nanos = Int64((time - Double(seconds)) * 1_000_000_000.0)
+        let normalized = Self.normalize(seconds: seconds, nanos: nanos)
+        self.seconds = normalized.seconds
+        self.nanos = normalized.nanos
+    }
+
+    public func toDate() -> Date {
+        Date(timeIntervalSince1970: Double(seconds) + Double(nanos) / 
1_000_000_000.0)
+    }
+
+    private static func normalize(seconds: Int64, nanos: Int64) -> (seconds: 
Int64, nanos: UInt32) {
+        var normalizedSeconds = seconds + nanos / 1_000_000_000
+        var normalizedNanos = nanos % 1_000_000_000
+        if normalizedNanos < 0 {
+            normalizedNanos += 1_000_000_000
+            normalizedSeconds -= 1
+        }
+        return (normalizedSeconds, UInt32(normalizedNanos))
+    }
+}
+
+extension Date: Serializer {
+    public static func foryDefault() -> Date {
+        Date(timeIntervalSince1970: 0)
+    }
+
+    public static var staticTypeId: ForyTypeId {
+        .timestamp
+    }
+
+    public func foryWriteData(_ context: WriteContext, hasGenerics: Bool) 
throws {
+        _ = hasGenerics
+        let ts = ForyTimestamp(date: self)
+        context.writer.writeInt64(ts.seconds)
+        context.writer.writeUInt32(ts.nanos)
+    }
+
+    public static func foryReadData(_ context: ReadContext) throws -> Date {
+        let ts = ForyTimestamp(seconds: try context.reader.readInt64(), nanos: 
try context.reader.readUInt32())
+        return ts.toDate()
+    }
+}
diff --git a/swift/Sources/ForySwift/FieldSkipper.swift 
b/swift/Sources/Fory/FieldSkipper.swift
similarity index 92%
rename from swift/Sources/ForySwift/FieldSkipper.swift
rename to swift/Sources/Fory/FieldSkipper.swift
index a9b0a4ce9..7d12b243e 100644
--- a/swift/Sources/ForySwift/FieldSkipper.swift
+++ b/swift/Sources/Fory/FieldSkipper.swift
@@ -84,6 +84,14 @@ public enum FieldSkipper {
             return fieldType.nullable
                 ? try String?.foryRead(context, refMode: refMode, 
readTypeInfo: false)
                 : try String.foryRead(context, refMode: refMode, readTypeInfo: 
false)
+        case ForyTypeId.timestamp.rawValue:
+            return fieldType.nullable
+                ? try Date?.foryRead(context, refMode: refMode, readTypeInfo: 
false)
+                : try Date.foryRead(context, refMode: refMode, readTypeInfo: 
false)
+        case ForyTypeId.date.rawValue:
+            return fieldType.nullable
+                ? try ForyDate?.foryRead(context, refMode: refMode, 
readTypeInfo: false)
+                : try ForyDate.foryRead(context, refMode: refMode, 
readTypeInfo: false)
         case ForyTypeId.list.rawValue:
             guard fieldType.generics.count == 1,
                   fieldType.generics[0].typeID == ForyTypeId.string.rawValue 
else {
diff --git a/swift/Sources/ForySwift/Fory.swift b/swift/Sources/Fory/Fory.swift
similarity index 100%
rename from swift/Sources/ForySwift/Fory.swift
rename to swift/Sources/Fory/Fory.swift
diff --git a/swift/Sources/ForySwift/ForyError.swift 
b/swift/Sources/Fory/ForyError.swift
similarity index 100%
rename from swift/Sources/ForySwift/ForyError.swift
rename to swift/Sources/Fory/ForyError.swift
diff --git a/swift/Sources/ForySwift/ForyFlags.swift 
b/swift/Sources/Fory/ForyFlags.swift
similarity index 100%
rename from swift/Sources/ForySwift/ForyFlags.swift
rename to swift/Sources/Fory/ForyFlags.swift
diff --git a/swift/Sources/ForySwift/ForyTypeId.swift 
b/swift/Sources/Fory/ForyTypeId.swift
similarity index 100%
rename from swift/Sources/ForySwift/ForyTypeId.swift
rename to swift/Sources/Fory/ForyTypeId.swift
diff --git a/swift/Sources/ForySwift/MacroDeclarations.swift 
b/swift/Sources/Fory/MacroDeclarations.swift
similarity index 88%
rename from swift/Sources/ForySwift/MacroDeclarations.swift
rename to swift/Sources/Fory/MacroDeclarations.swift
index db59b374c..a08cc5c57 100644
--- a/swift/Sources/ForySwift/MacroDeclarations.swift
+++ b/swift/Sources/Fory/MacroDeclarations.swift
@@ -26,7 +26,7 @@
     named(foryReadData)
 )
 @attached(extension, conformances: Serializer)
-public macro ForyObject() = #externalMacro(module: "ForySwiftMacros", type: 
"ForyObjectMacro")
+public macro ForyObject() = #externalMacro(module: "ForyMacro", type: 
"ForyObjectMacro")
 
 public enum ForyFieldEncoding: String {
     case varint
@@ -37,4 +37,4 @@ public enum ForyFieldEncoding: String {
 @attached(peer)
 public macro ForyField(
     encoding: ForyFieldEncoding
-) = #externalMacro(module: "ForySwiftMacros", type: "ForyFieldMacro")
+) = #externalMacro(module: "ForyMacro", type: "ForyFieldMacro")
diff --git a/swift/Sources/ForySwift/MetaString.swift 
b/swift/Sources/Fory/MetaString.swift
similarity index 100%
rename from swift/Sources/ForySwift/MetaString.swift
rename to swift/Sources/Fory/MetaString.swift
diff --git a/swift/Sources/ForySwift/MurmurHash3.swift 
b/swift/Sources/Fory/MurmurHash3.swift
similarity index 100%
rename from swift/Sources/ForySwift/MurmurHash3.swift
rename to swift/Sources/Fory/MurmurHash3.swift
diff --git a/swift/Sources/ForySwift/OptionalSerializer.swift 
b/swift/Sources/Fory/OptionalSerializer.swift
similarity index 100%
rename from swift/Sources/ForySwift/OptionalSerializer.swift
rename to swift/Sources/Fory/OptionalSerializer.swift
diff --git a/swift/Sources/ForySwift/PrimitiveSerializers.swift 
b/swift/Sources/Fory/PrimitiveSerializers.swift
similarity index 100%
rename from swift/Sources/ForySwift/PrimitiveSerializers.swift
rename to swift/Sources/Fory/PrimitiveSerializers.swift
diff --git a/swift/Sources/ForySwift/RefResolver.swift 
b/swift/Sources/Fory/RefResolver.swift
similarity index 100%
rename from swift/Sources/ForySwift/RefResolver.swift
rename to swift/Sources/Fory/RefResolver.swift
diff --git a/swift/Sources/ForySwift/SchemaHash.swift 
b/swift/Sources/Fory/SchemaHash.swift
similarity index 100%
rename from swift/Sources/ForySwift/SchemaHash.swift
rename to swift/Sources/Fory/SchemaHash.swift
diff --git a/swift/Sources/ForySwift/Serializer.swift 
b/swift/Sources/Fory/Serializer.swift
similarity index 100%
rename from swift/Sources/ForySwift/Serializer.swift
rename to swift/Sources/Fory/Serializer.swift
diff --git a/swift/Sources/ForySwift/TypeMeta.swift 
b/swift/Sources/Fory/TypeMeta.swift
similarity index 100%
rename from swift/Sources/ForySwift/TypeMeta.swift
rename to swift/Sources/Fory/TypeMeta.swift
diff --git a/swift/Sources/ForySwift/TypeResolver.swift 
b/swift/Sources/Fory/TypeResolver.swift
similarity index 98%
rename from swift/Sources/ForySwift/TypeResolver.swift
rename to swift/Sources/Fory/TypeResolver.swift
index 2e4a95fa9..a9959ba6e 100644
--- a/swift/Sources/ForySwift/TypeResolver.swift
+++ b/swift/Sources/Fory/TypeResolver.swift
@@ -294,6 +294,10 @@ public final class TypeResolver {
             value = try Double.foryRead(context, refMode: .none, readTypeInfo: 
false)
         case .string:
             value = try String.foryRead(context, refMode: .none, readTypeInfo: 
false)
+        case .timestamp:
+            value = try Date.foryRead(context, refMode: .none, readTypeInfo: 
false)
+        case .date:
+            value = try ForyDate.foryRead(context, refMode: .none, 
readTypeInfo: false)
         case .binary, .uint8Array:
             value = try Data.foryRead(context, refMode: .none, readTypeInfo: 
false)
         case .boolArray:
diff --git a/swift/Sources/ForySwiftMacros/ForyObjectMacro.swift 
b/swift/Sources/ForyMacro/ForyObjectMacro.swift
similarity index 84%
rename from swift/Sources/ForySwiftMacros/ForyObjectMacro.swift
rename to swift/Sources/ForyMacro/ForyObjectMacro.swift
index b0a5bc5f3..0a71a9ca2 100644
--- a/swift/Sources/ForySwiftMacros/ForyObjectMacro.swift
+++ b/swift/Sources/ForyMacro/ForyObjectMacro.swift
@@ -33,6 +33,11 @@ public struct ForyObjectMacro: MemberMacro, ExtensionMacro {
         conformingTo _: [TypeSyntax],
         in _: some MacroExpansionContext
     ) throws -> [DeclSyntax] {
+        if let enumDecl = declaration.as(EnumDeclSyntax.self) {
+            let parsedEnum = try parseEnumDecl(enumDecl)
+            return buildEnumDecls(parsedEnum)
+        }
+
         let parsed = try parseFields(declaration)
         let sortedFields = sortFields(parsed.fields)
 
@@ -75,6 +80,8 @@ public struct ForyObjectMacro: MemberMacro, ExtensionMacro {
             typeName = structDecl.name
         } else if let classDecl = declaration.as(ClassDeclSyntax.self) {
             typeName = classDecl.name
+        } else if let enumDecl = declaration.as(EnumDeclSyntax.self) {
+            typeName = enumDecl.name
         } else {
             return []
         }
@@ -129,11 +136,252 @@ private struct ParsedDecl {
     let fields: [ParsedField]
 }
 
+private enum ParsedEnumKind {
+    case ordinal
+    case taggedUnion
+}
+
+private struct ParsedEnumPayloadField {
+    let label: String?
+    let typeText: String
+    let hasGenerics: Bool
+}
+
+private struct ParsedEnumCase {
+    let name: String
+    let payload: [ParsedEnumPayloadField]
+}
+
+private struct ParsedEnumDecl {
+    let kind: ParsedEnumKind
+    let cases: [ParsedEnumCase]
+}
+
 private struct FieldTypeResolution {
     let classification: TypeClassification
     let customCodecType: String?
 }
 
+private func parseEnumDecl(_ enumDecl: EnumDeclSyntax) throws -> 
ParsedEnumDecl {
+    var cases: [ParsedEnumCase] = []
+
+    for member in enumDecl.memberBlock.members {
+        guard let caseDecl = member.decl.as(EnumCaseDeclSyntax.self) else {
+            continue
+        }
+
+        for element in caseDecl.elements {
+            let caseName = element.name.text
+            if caseName.isEmpty {
+                continue
+            }
+
+            var payloadFields: [ParsedEnumPayloadField] = []
+            if let parameterClause = element.parameterClause {
+                for parameter in parameterClause.parameters {
+                    if parameter.defaultValue != nil {
+                        throw MacroExpansionErrorMessage(
+                            "@ForyObject enum associated values cannot have 
default values"
+                        )
+                    }
+
+                    let payloadType = parameter.type.trimmedDescription
+                    let optional = unwrapOptional(payloadType)
+                    let classification = classifyType(optional.type)
+                    let hasGenerics = classification.isCollection || 
classification.isMap
+                    let label: String?
+                    if let firstName = parameter.firstName, firstName.text != 
"_" {
+                        label = firstName.text
+                    } else {
+                        label = nil
+                    }
+
+                    payloadFields.append(
+                        .init(
+                            label: label,
+                            typeText: payloadType,
+                            hasGenerics: hasGenerics
+                        )
+                    )
+                }
+            }
+            cases.append(.init(name: caseName, payload: payloadFields))
+        }
+    }
+
+    guard !cases.isEmpty else {
+        throw MacroExpansionErrorMessage("@ForyObject enum must define at 
least one case")
+    }
+
+    let hasPayload = cases.contains { !$0.payload.isEmpty }
+    if hasPayload {
+        return .init(kind: .taggedUnion, cases: cases)
+    }
+
+    return .init(kind: .ordinal, cases: cases)
+}
+
+private func buildEnumDecls(_ parsedEnum: ParsedEnumDecl) -> [DeclSyntax] {
+    switch parsedEnum.kind {
+    case .ordinal:
+        return buildOrdinalEnumDecls(parsedEnum.cases)
+    case .taggedUnion:
+        return buildTaggedUnionEnumDecls(parsedEnum.cases)
+    }
+}
+
+private func buildOrdinalEnumDecls(_ cases: [ParsedEnumCase]) -> [DeclSyntax] {
+    let defaultCase = cases[0].name
+    let writeSwitchCases = cases.enumerated().map { index, enumCase in
+        """
+        case .\(enumCase.name):
+            context.writer.writeVarUInt32(\(index))
+        """
+    }.joined(separator: "\n        ")
+    let readSwitchCases = cases.enumerated().map { index, enumCase in
+        "case \(index): return .\(enumCase.name)"
+    }.joined(separator: "\n        ")
+
+    let defaultDecl: DeclSyntax = DeclSyntax(
+        stringLiteral: """
+        static func foryDefault() -> Self {
+            .\(defaultCase)
+        }
+        """
+    )
+
+    let staticTypeIDDecl: DeclSyntax = """
+    static var staticTypeId: ForyTypeId { .enumType }
+    """
+
+    let writeDecl: DeclSyntax = DeclSyntax(
+        stringLiteral: """
+        func foryWriteData(_ context: WriteContext, hasGenerics: Bool) throws {
+            _ = hasGenerics
+            switch self {
+            \(writeSwitchCases)
+            }
+        }
+        """
+    )
+
+    let readDecl: DeclSyntax = DeclSyntax(
+        stringLiteral: """
+        static func foryReadData(_ context: ReadContext) throws -> Self {
+            let ordinal = try context.reader.readVarUInt32()
+            switch ordinal {
+            \(readSwitchCases)
+            default:
+                throw ForyError.invalidData("unknown enum ordinal \\(ordinal)")
+            }
+        }
+        """
+    )
+
+    return [defaultDecl, staticTypeIDDecl, writeDecl, readDecl]
+}
+
+private func buildTaggedUnionEnumDecls(_ cases: [ParsedEnumCase]) -> 
[DeclSyntax] {
+    let defaultExpr = enumCaseDefaultExpr(cases[0])
+    let writeSwitchCases = cases.enumerated().map { index, enumCase in
+        var lines: [String] = []
+        lines.append("case \(enumCasePattern(enumCase)):")
+        lines.append("    context.writer.writeVarUInt32(\(index))")
+        for payloadIndex in enumCase.payload.indices {
+            let variableName = "__value\(payloadIndex)"
+            let hasGenerics = enumCase.payload[payloadIndex].hasGenerics ? 
"true" : "false"
+            lines.append(
+                "    try \(variableName).foryWrite(context, refMode: 
.tracking, writeTypeInfo: true, hasGenerics: \(hasGenerics))"
+            )
+        }
+        return lines.joined(separator: "\n")
+    }.joined(separator: "\n        ")
+
+    let readSwitchCases = cases.enumerated().map { index, enumCase in
+        if enumCase.payload.isEmpty {
+            return """
+            case \(index):
+                return .\(enumCase.name)
+            """
+        }
+
+        var lines: [String] = ["case \(index):"]
+        for (payloadIndex, payloadField) in enumCase.payload.enumerated() {
+            lines.append(
+                "    let __value\(payloadIndex) = try 
\(payloadField.typeText).foryRead(context, refMode: .tracking, readTypeInfo: 
true)"
+            )
+        }
+        let ctorArgs = enumCase.payload.enumerated().map { payloadIndex, 
payloadField in
+            if let label = payloadField.label {
+                return "\(label): __value\(payloadIndex)"
+            }
+            return "__value\(payloadIndex)"
+        }.joined(separator: ", ")
+        lines.append("    return .\(enumCase.name)(\(ctorArgs))")
+        return lines.joined(separator: "\n")
+    }.joined(separator: "\n        ")
+
+    let defaultDecl: DeclSyntax = DeclSyntax(
+        stringLiteral: """
+        static func foryDefault() -> Self {
+            \(defaultExpr)
+        }
+        """
+    )
+
+    let staticTypeIDDecl: DeclSyntax = """
+    static var staticTypeId: ForyTypeId { .typedUnion }
+    """
+
+    let writeDecl: DeclSyntax = DeclSyntax(
+        stringLiteral: """
+        func foryWriteData(_ context: WriteContext, hasGenerics: Bool) throws {
+            _ = hasGenerics
+            switch self {
+            \(writeSwitchCases)
+            }
+        }
+        """
+    )
+
+    let readDecl: DeclSyntax = DeclSyntax(
+        stringLiteral: """
+        static func foryReadData(_ context: ReadContext) throws -> Self {
+            let caseID = try context.reader.readVarUInt32()
+            switch caseID {
+            \(readSwitchCases)
+            default:
+                throw ForyError.invalidData("unknown union tag \\(caseID)")
+            }
+        }
+        """
+    )
+
+    return [defaultDecl, staticTypeIDDecl, writeDecl, readDecl]
+}
+
+private func enumCasePattern(_ enumCase: ParsedEnumCase) -> String {
+    guard !enumCase.payload.isEmpty else {
+        return ".\(enumCase.name)"
+    }
+    let bindings = enumCase.payload.indices.map { "let __value\($0)" 
}.joined(separator: ", ")
+    return ".\(enumCase.name)(\(bindings))"
+}
+
+private func enumCaseDefaultExpr(_ enumCase: ParsedEnumCase) -> String {
+    guard !enumCase.payload.isEmpty else {
+        return ".\(enumCase.name)"
+    }
+    let args = enumCase.payload.map { payloadField in
+        let defaultValue = "\(payloadField.typeText).foryDefault()"
+        if let label = payloadField.label {
+            return "\(label): \(defaultValue)"
+        }
+        return defaultValue
+    }.joined(separator: ", ")
+    return ".\(enumCase.name)(\(args))"
+}
+
 private func parseFields(_ declaration: some DeclGroupSyntax) throws -> 
ParsedDecl {
     let isClass = declaration.is(ClassDeclSyntax.self)
     guard isClass || declaration.is(StructDeclSyntax.self) else {
@@ -1046,6 +1294,10 @@ private func classifyType(_ typeText: String) -> 
TypeClassification {
         return .init(typeID: 21, isPrimitive: false, isBuiltIn: true, 
isCollection: false, isMap: false, isCompressedNumeric: false, primitiveSize: 0)
     case "Data", "Foundation.Data":
         return .init(typeID: 41, isPrimitive: false, isBuiltIn: true, 
isCollection: false, isMap: false, isCompressedNumeric: false, primitiveSize: 0)
+    case "Date", "Foundation.Date", "ForyTimestamp":
+        return .init(typeID: 38, isPrimitive: false, isBuiltIn: true, 
isCollection: false, isMap: false, isCompressedNumeric: false, primitiveSize: 0)
+    case "ForyDate":
+        return .init(typeID: 39, isPrimitive: false, isBuiltIn: true, 
isCollection: false, isMap: false, isCompressedNumeric: false, primitiveSize: 0)
     default:
         break
     }
diff --git a/swift/Tests/ForyTests/DateTimeTests.swift 
b/swift/Tests/ForyTests/DateTimeTests.swift
new file mode 100644
index 000000000..399b20479
--- /dev/null
+++ b/swift/Tests/ForyTests/DateTimeTests.swift
@@ -0,0 +1,75 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+import Foundation
+import Testing
+@testable import Fory
+
+@ForyObject
+private struct DateMacroHolder {
+    var day: ForyDate = .init()
+    var instant: Date = .foryDefault()
+    var timestamp: ForyTimestamp = .init()
+}
+
+@Test
+func dateAndTimestampTypeIds() {
+    #expect(ForyDate.staticTypeId == .date)
+    #expect(ForyTimestamp.staticTypeId == .timestamp)
+    #expect(Date.staticTypeId == .timestamp)
+}
+
+@Test
+func dateAndTimestampRoundTrip() throws {
+    let fory = Fory()
+
+    let day = ForyDate(daysSinceEpoch: 18_745)
+    let dayData = try fory.serialize(day)
+    let dayDecoded: ForyDate = try fory.deserialize(dayData)
+    #expect(dayDecoded == day)
+
+    let ts = ForyTimestamp(seconds: -123, nanos: 987_654_321)
+    let tsData = try fory.serialize(ts)
+    let tsDecoded: ForyTimestamp = try fory.deserialize(tsData)
+    #expect(tsDecoded == ts)
+
+    let instant = Date(timeIntervalSince1970: 1_731_234_567.123_456_7)
+    let instantData = try fory.serialize(instant)
+    let instantDecoded: Date = try fory.deserialize(instantData)
+    let diff = abs(instantDecoded.timeIntervalSince1970 - 
instant.timeIntervalSince1970)
+    #expect(diff < 0.000_001)
+}
+
+@Test
+func dateAndTimestampMacroFieldRoundTrip() throws {
+    let fory = Fory(config: .init(xlang: true, trackRef: false, compatible: 
true))
+    fory.register(DateMacroHolder.self, id: 901)
+
+    let value = DateMacroHolder(
+        day: .init(daysSinceEpoch: 20_001),
+        instant: Date(timeIntervalSince1970: 123_456.000_001),
+        timestamp: .init(seconds: 44, nanos: 12_345)
+    )
+
+    let data = try fory.serialize(value)
+    let decoded: DateMacroHolder = try fory.deserialize(data)
+
+    #expect(decoded.day == value.day)
+    #expect(decoded.timestamp == value.timestamp)
+    let diff = abs(decoded.instant.timeIntervalSince1970 - 
value.instant.timeIntervalSince1970)
+    #expect(diff < 0.000_001)
+}
diff --git a/swift/Tests/ForyTests/EnumTests.swift 
b/swift/Tests/ForyTests/EnumTests.swift
new file mode 100644
index 000000000..4053066ee
--- /dev/null
+++ b/swift/Tests/ForyTests/EnumTests.swift
@@ -0,0 +1,120 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+import Foundation
+import Testing
+@testable import Fory
+
+@ForyObject
+private enum Color: Equatable {
+    case red
+    case green
+    case blue
+}
+
+@ForyObject
+private enum StringOrLong: Equatable {
+    case text(String)
+    case number(Int64)
+}
+
+@ForyObject
+private struct StructWithEnum: Equatable {
+    var name: String = ""
+    var color: Color = .red
+    var value: Int32 = 0
+}
+
+@ForyObject
+private struct StructWithUnion: Equatable {
+    var unionField: StringOrLong = .foryDefault()
+}
+
+@ForyObject
+private indirect enum Token: Equatable {
+    case plus
+    case number(Int64)
+    case ident(String)
+    case assign(target: String, value: Int32)
+    case other(Int64?)
+    case child(Token)
+    case map([String: Token])
+}
+
+@Test
+func enumTypeIdClassification() {
+    #expect(Color.staticTypeId == .enumType)
+    #expect(StringOrLong.staticTypeId == .typedUnion)
+}
+
+@Test
+func structWithEnumFieldRoundTrip() throws {
+    let fory = Fory(config: .init(xlang: true, trackRef: false, compatible: 
false))
+    fory.register(Color.self, id: 100)
+    fory.register(StructWithEnum.self, id: 101)
+
+    let value = StructWithEnum(name: "test", color: .green, value: 42)
+    let data = try fory.serialize(value)
+    let decoded: StructWithEnum = try fory.deserialize(data)
+    #expect(decoded == value)
+}
+
+@Test
+func taggedUnionXlangRoundTrip() throws {
+    let fory = Fory(config: .init(xlang: true, trackRef: false, compatible: 
false))
+    fory.register(StringOrLong.self, id: 300)
+    fory.register(StructWithUnion.self, id: 301)
+
+    let first = StructWithUnion(unionField: .text("hello"))
+    let second = StructWithUnion(unionField: .number(42))
+
+    let firstData = try fory.serialize(first)
+    let secondData = try fory.serialize(second)
+
+    let firstDecoded: StructWithUnion = try fory.deserialize(firstData)
+    let secondDecoded: StructWithUnion = try fory.deserialize(secondData)
+
+    #expect(firstDecoded == first)
+    #expect(secondDecoded == second)
+}
+
+@Test
+func mixedEnumShapesRoundTrip() throws {
+    let fory = Fory(config: .init(xlang: false, trackRef: true, compatible: 
false))
+    fory.register(Token.self, id: 1000)
+
+    let nestedMap: [String: Token] = [
+        "one": .number(1),
+        "plus": .plus,
+        "nested": .child(.ident("deep")),
+    ]
+
+    let tokens: [Token] = [
+        .plus,
+        .number(1),
+        .ident("foo"),
+        .assign(target: "bar", value: 42),
+        .other(42),
+        .other(nil),
+        .child(.child(.other(nil))),
+        .map(nestedMap),
+    ]
+
+    let data = try fory.serialize(tokens)
+    let decoded: [Token] = try fory.deserialize(data)
+    #expect(decoded == tokens)
+}
diff --git a/swift/Tests/ForySwiftTests/ForySwiftTests.swift 
b/swift/Tests/ForyTests/ForySwiftTests.swift
similarity index 97%
rename from swift/Tests/ForySwiftTests/ForySwiftTests.swift
rename to swift/Tests/ForyTests/ForySwiftTests.swift
index 7f85a7233..4d6667b67 100644
--- a/swift/Tests/ForySwiftTests/ForySwiftTests.swift
+++ b/swift/Tests/ForyTests/ForySwiftTests.swift
@@ -17,7 +17,7 @@
 
 import Foundation
 import Testing
-@testable import ForySwift
+@testable import Fory
 
 @ForyObject
 struct Address: Equatable {
@@ -66,6 +66,19 @@ final class Node {
     }
 }
 
+@ForyObject
+final class WeakNode {
+    var value: Int32 = 0
+    weak var next: WeakNode?
+
+    required init() {}
+
+    init(value: Int32, next: WeakNode? = nil) {
+        self.value = value
+        self.next = next
+    }
+}
+
 @ForyObject
 struct AnyObjectHolder {
     var value: AnyObject
@@ -232,6 +245,21 @@ func macroClassReferenceTracking() throws {
     #expect(decoded.next === decoded)
 }
 
+@Test
+func macroClassWeakReferenceTracking() throws {
+    let fory = Fory(config: .init(xlang: true, trackRef: true))
+    fory.register(WeakNode.self, id: 201)
+
+    let node = WeakNode(value: 13)
+    node.next = node
+
+    let data = try fory.serialize(node)
+    let decoded: WeakNode = try fory.deserialize(data)
+
+    #expect(decoded.value == 13)
+    #expect(decoded.next === decoded)
+}
+
 @Test
 func topLevelAnyRoundTrip() throws {
     let fory = Fory()
diff --git a/swift/Sources/ForySwiftXlangPeer/main.swift 
b/swift/Tests/ForyXlangPeer/main.swift
similarity index 90%
rename from swift/Sources/ForySwiftXlangPeer/main.swift
rename to swift/Tests/ForyXlangPeer/main.swift
index d29404f8a..c6b935802 100644
--- a/swift/Sources/ForySwiftXlangPeer/main.swift
+++ b/swift/Tests/ForyXlangPeer/main.swift
@@ -16,93 +16,23 @@
 // under the License.
 
 import Foundation
-import ForySwift
+import Fory
 
 // MARK: - Shared test types
 
-private enum PeerColor: UInt32 {
-    case green = 0
-    case red = 1
-    case blue = 2
-    case white = 3
-}
-
-private enum PeerTestEnum: UInt32 {
-    case valueA = 0
-    case valueB = 1
-    case valueC = 2
-}
-
-private protocol PeerUInt32EnumSerializer: RawRepresentable, Serializer where 
RawValue == UInt32 {}
-
-extension PeerUInt32EnumSerializer {
-    static func foryDefault() -> Self {
-        Self(rawValue: 0)!
-    }
-
-    static var staticTypeId: ForyTypeId {
-        .enumType
-    }
-
-    func foryWriteData(_ context: WriteContext, hasGenerics: Bool) throws {
-        _ = hasGenerics
-        context.writer.writeVarUInt32(rawValue)
-    }
-
-    static func foryReadData(_ context: ReadContext) throws -> Self {
-        let ordinal = try context.reader.readVarUInt32()
-        guard let value = Self(rawValue: ordinal) else {
-            throw ForyError.invalidData("unknown enum ordinal \(ordinal)")
-        }
-        return value
-    }
-}
-
-extension PeerColor: PeerUInt32EnumSerializer {}
-extension PeerTestEnum: PeerUInt32EnumSerializer {}
-
-private struct PeerDate: Serializer, Equatable {
-    var daysSinceEpoch: Int32 = 0
-
-    static func foryDefault() -> PeerDate {
-        PeerDate()
-    }
-
-    static var staticTypeId: ForyTypeId {
-        .date
-    }
-
-    func foryWriteData(_ context: WriteContext, hasGenerics: Bool) throws {
-        _ = hasGenerics
-        context.writer.writeInt32(daysSinceEpoch)
-    }
-
-    static func foryReadData(_ context: ReadContext) throws -> PeerDate {
-        PeerDate(daysSinceEpoch: try context.reader.readInt32())
-    }
+@ForyObject
+private enum PeerColor {
+    case green
+    case red
+    case blue
+    case white
 }
 
-private struct PeerTimestamp: Serializer, Equatable {
-    var seconds: Int64 = 0
-    var nanos: Int32 = 0
-
-    static func foryDefault() -> PeerTimestamp {
-        PeerTimestamp()
-    }
-
-    static var staticTypeId: ForyTypeId {
-        .timestamp
-    }
-
-    func foryWriteData(_ context: WriteContext, hasGenerics: Bool) throws {
-        _ = hasGenerics
-        context.writer.writeInt64(seconds)
-        context.writer.writeInt32(nanos)
-    }
-
-    static func foryReadData(_ context: ReadContext) throws -> PeerTimestamp {
-        PeerTimestamp(seconds: try context.reader.readInt64(), nanos: try 
context.reader.readInt32())
-    }
+@ForyObject
+private enum PeerTestEnum {
+    case valueA
+    case valueB
+    case valueC
 }
 
 @ForyObject
@@ -286,7 +216,7 @@ private final class RefOverrideContainer {
 @ForyObject
 private final class CircularRefStruct {
     var name: String = ""
-    var selfRef: CircularRefStruct? = nil
+    weak var selfRef: CircularRefStruct? = nil
 
     required init() {}
 }
@@ -349,43 +279,10 @@ private struct AnimalMapHolder {
     var animalMap: [String: Any] = [:]
 }
 
-private enum StringOrLong: Serializer, Equatable {
-    case str(String)
-    case long(Int64)
-
-    static func foryDefault() -> StringOrLong {
-        .str("")
-    }
-
-    static var staticTypeId: ForyTypeId {
-        .typedUnion
-    }
-
-    func foryWriteData(_ context: WriteContext, hasGenerics: Bool) throws {
-        _ = hasGenerics
-        switch self {
-        case .str(let value):
-            context.writer.writeVarUInt32(0)
-            try value.foryWrite(context, refMode: .tracking, writeTypeInfo: 
true, hasGenerics: false)
-        case .long(let value):
-            context.writer.writeVarUInt32(1)
-            try value.foryWrite(context, refMode: .tracking, writeTypeInfo: 
true, hasGenerics: false)
-        }
-    }
-
-    static func foryReadData(_ context: ReadContext) throws -> StringOrLong {
-        let tag = try context.reader.readVarUInt32()
-        switch tag {
-        case 0:
-            let value: String = try String.foryRead(context, refMode: 
.tracking, readTypeInfo: true)
-            return .str(value)
-        case 1:
-            let value: Int64 = try Int64.foryRead(context, refMode: .tracking, 
readTypeInfo: true)
-            return .long(value)
-        default:
-            throw ForyError.invalidData("unknown union tag \(tag)")
-        }
-    }
+@ForyObject
+private enum StringOrLong {
+    case text(String)
+    case number(Int64)
 }
 
 @ForyObject
@@ -601,8 +498,8 @@ private func handleCrossLanguageSerializer(_ bytes: 
[UInt8]) throws -> [UInt8] {
         let f32: Float = try fory.deserializeFrom(reader)
         let f64: Double = try fory.deserializeFrom(reader)
         let str: String = try fory.deserializeFrom(reader)
-        let day: PeerDate = try fory.deserializeFrom(reader)
-        let ts: PeerTimestamp = try fory.deserializeFrom(reader)
+        let day: ForyDate = try fory.deserializeFrom(reader)
+        let ts: ForyTimestamp = try fory.deserializeFrom(reader)
         let boolArray: [Bool] = try fory.deserializeFrom(reader)
         let byteArray: [UInt8] = try fory.deserializeFrom(reader)
         let shortArray: [Int16] = try fory.deserializeFrom(reader)


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]


Reply via email to