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

imbruced pushed a commit to branch add-sedona-deserializer
in repository https://gitbox.apache.org/repos/asf/sedona-db.git

commit 9100359e29c2266b01217e47f22ec7d02345d512
Author: pawelkocinski <[email protected]>
AuthorDate: Mon Dec 15 23:24:37 2025 +0100

    add sedona deserialization code
---
 Cargo.lock                                         | 288 +++++++++------
 Cargo.toml                                         |   1 +
 rust/sedona-functions/Cargo.toml                   |   1 +
 .../sedona-functions/src/fixtures/crs_point.sedona |  11 +
 .../src/fixtures/empty_geometry_collection.sedona  |   5 +
 .../src/fixtures/empty_linestring.sedona           |   5 +
 .../src/fixtures/empty_multilinestring.sedona      |   5 +
 .../src/fixtures/empty_multipolygon.sedona         |   5 +
 .../src/fixtures/empty_point.sedona                |   5 +
 .../src/fixtures/empty_polygon.sedona              |   5 +
 .../src/fixtures/geometrycollection.sedona         |  42 +++
 .../src/fixtures/geometrycollectioncomplex.sedona  |  52 +++
 .../src/fixtures/linestring.sedona                 |  13 +
 .../src/fixtures/multilinestring.sedona            |  25 ++
 .../src/fixtures/multipoint.sedona                 |  13 +
 .../src/fixtures/multipoint_empty.sedona           |   5 +
 .../src/fixtures/multipolygon.sedona               |  65 ++++
 .../src/fixtures/nested_geometry_collection.sedona |  46 +++
 rust/sedona-functions/src/fixtures/point.sedona    |  11 +
 .../src/fixtures/point_float_coords.sedona         |  42 +++
 rust/sedona-functions/src/fixtures/polygon.sedona  |  41 +++
 rust/sedona-functions/src/lib.rs                   |   1 +
 rust/sedona-functions/src/register.rs              |   1 +
 rust/sedona-functions/src/st_from_sedona_spark.rs  | 387 +++++++++++++++++++++
 rust/{sedona-functions => sedona-serde}/Cargo.toml |  25 +-
 rust/sedona-serde/src/deserialize.rs               | 130 +++++++
 rust/sedona-serde/src/lib.rs                       |  22 ++
 rust/sedona-serde/src/linestring.rs                |  98 ++++++
 rust/sedona-serde/src/point.rs                     |  96 +++++
 rust/sedona-serde/src/polygon.rs                   | 104 ++++++
 rust/sedona-serde/src/wkb.rs                       |  24 ++
 31 files changed, 1439 insertions(+), 135 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 23630f62..a1b060dc 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -56,8 +56,8 @@ version = "0.21.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "1a38cdcc3e43dc645038c2b6339dd98610c48ae593cc67839452e6670fa09f27"
 dependencies = [
- "arrow-array",
- "arrow-schema",
+ "arrow-array 57.1.0",
+ "arrow-schema 57.1.0",
 ]
 
 [[package]]
@@ -67,8 +67,8 @@ source = 
"registry+https://github.com/rust-lang/crates.io-index";
 checksum = "08d36274376fdc4849cf47a78f3baeef4ae1654ef703dc3148d91adde3336c11"
 dependencies = [
  "adbc_core",
- "arrow-array",
- "arrow-schema",
+ "arrow-array 57.1.0",
+ "arrow-schema 57.1.0",
 ]
 
 [[package]]
@@ -267,16 +267,16 @@ source = 
"registry+https://github.com/rust-lang/crates.io-index";
 checksum = "fd798aea3553913a5986813e9c6ad31a2d2b04e931fe8ea4a37155eb541cebb5"
 dependencies = [
  "arrow-arith",
- "arrow-array",
- "arrow-buffer",
+ "arrow-array 56.2.0",
+ "arrow-buffer 56.2.0",
  "arrow-cast",
  "arrow-csv",
- "arrow-data",
+ "arrow-data 56.2.0",
  "arrow-ipc",
  "arrow-json",
  "arrow-ord",
  "arrow-row",
- "arrow-schema",
+ "arrow-schema 56.2.0",
  "arrow-select",
  "arrow-string",
 ]
@@ -287,52 +287,82 @@ version = "56.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "508dafb53e5804a238cab7fd97a59ddcbfab20cc4d9814b1ab5465b9fa147f2e"
 dependencies = [
- "arrow-array",
- "arrow-buffer",
- "arrow-data",
- "arrow-schema",
+ "arrow-array 56.2.0",
+ "arrow-buffer 56.2.0",
+ "arrow-data 56.2.0",
+ "arrow-schema 56.2.0",
  "chrono",
  "num",
 ]
 
 [[package]]
 name = "arrow-array"
-version = "56.0.0"
+version = "56.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "e2730bc045d62bb2e53ef8395b7d4242f5c8102f41ceac15e8395b9ac3d08461"
+checksum = "8548ca7c070d8db9ce7aa43f37393e4bfcf3f2d3681df278490772fd1673d08d"
 dependencies = [
  "ahash",
- "arrow-buffer",
- "arrow-data",
- "arrow-schema",
+ "arrow-buffer 56.2.0",
+ "arrow-data 56.2.0",
+ "arrow-schema 56.2.0",
  "chrono",
  "chrono-tz",
  "half",
- "hashbrown 0.15.5",
+ "hashbrown 0.16.1",
  "num",
 ]
 
+[[package]]
+name = "arrow-array"
+version = "57.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "a23eaff85a44e9fa914660fb0d0bb00b79c4a3d888b5334adb3ea4330c84f002"
+dependencies = [
+ "ahash",
+ "arrow-buffer 57.1.0",
+ "arrow-data 57.1.0",
+ "arrow-schema 57.1.0",
+ "chrono",
+ "half",
+ "hashbrown 0.16.1",
+ "num-complex",
+ "num-integer",
+ "num-traits",
+]
+
 [[package]]
 name = "arrow-buffer"
-version = "56.0.0"
+version = "56.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "54295b93beb702ee9a6f6fbced08ad7f4d76ec1c297952d4b83cf68755421d1d"
+checksum = "e003216336f70446457e280807a73899dd822feaf02087d31febca1363e2fccc"
 dependencies = [
  "bytes",
  "half",
  "num",
 ]
 
+[[package]]
+name = "arrow-buffer"
+version = "57.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "a2819d893750cb3380ab31ebdc8c68874dd4429f90fd09180f3c93538bd21626"
+dependencies = [
+ "bytes",
+ "half",
+ "num-bigint",
+ "num-traits",
+]
+
 [[package]]
 name = "arrow-cast"
 version = "56.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "67e8bcb7dc971d779a7280593a1bf0c2743533b8028909073e804552e85e75b5"
 dependencies = [
- "arrow-array",
- "arrow-buffer",
- "arrow-data",
- "arrow-schema",
+ "arrow-array 56.2.0",
+ "arrow-buffer 56.2.0",
+ "arrow-data 56.2.0",
+ "arrow-schema 56.2.0",
  "arrow-select",
  "atoi",
  "base64",
@@ -350,9 +380,9 @@ version = "56.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "673fd2b5fb57a1754fdbfac425efd7cf54c947ac9950c1cce86b14e248f1c458"
 dependencies = [
- "arrow-array",
+ "arrow-array 56.2.0",
  "arrow-cast",
- "arrow-schema",
+ "arrow-schema 56.2.0",
  "chrono",
  "csv",
  "csv-core",
@@ -361,26 +391,40 @@ dependencies = [
 
 [[package]]
 name = "arrow-data"
-version = "56.0.0"
+version = "56.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "97c22fe3da840039c69e9f61f81e78092ea36d57037b4900151f063615a2f6b4"
+checksum = "a5c64fff1d142f833d78897a772f2e5b55b36cb3e6320376f0961ab0db7bd6d0"
 dependencies = [
- "arrow-buffer",
- "arrow-schema",
+ "arrow-buffer 56.2.0",
+ "arrow-schema 56.2.0",
  "half",
  "num",
 ]
 
+[[package]]
+name = "arrow-data"
+version = "57.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "05738f3d42cb922b9096f7786f606fcb8669260c2640df8490533bb2fa38c9d3"
+dependencies = [
+ "arrow-buffer 57.1.0",
+ "arrow-schema 57.1.0",
+ "half",
+ "num-integer",
+ "num-traits",
+]
+
 [[package]]
 name = "arrow-ipc"
-version = "56.0.0"
+version = "56.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "778de14c5a69aedb27359e3dd06dd5f9c481d5f6ee9fbae912dba332fd64636b"
+checksum = "1d3594dcddccc7f20fd069bc8e9828ce37220372680ff638c5e00dea427d88f5"
 dependencies = [
- "arrow-array",
- "arrow-buffer",
- "arrow-data",
- "arrow-schema",
+ "arrow-array 56.2.0",
+ "arrow-buffer 56.2.0",
+ "arrow-data 56.2.0",
+ "arrow-schema 56.2.0",
+ "arrow-select",
  "flatbuffers",
  "lz4_flex",
  "zstd",
@@ -392,11 +436,11 @@ version = "56.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "3860db334fe7b19fcf81f6b56f8d9d95053f3839ffe443d56b5436f7a29a1794"
 dependencies = [
- "arrow-array",
- "arrow-buffer",
+ "arrow-array 56.2.0",
+ "arrow-buffer 56.2.0",
  "arrow-cast",
- "arrow-data",
- "arrow-schema",
+ "arrow-data 56.2.0",
+ "arrow-schema 56.2.0",
  "chrono",
  "half",
  "indexmap",
@@ -414,10 +458,10 @@ version = "56.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "425fa0b42a39d3ff55160832e7c25553e7f012c3f187def3d70313e7a29ba5d9"
 dependencies = [
- "arrow-array",
- "arrow-buffer",
- "arrow-data",
- "arrow-schema",
+ "arrow-array 56.2.0",
+ "arrow-buffer 56.2.0",
+ "arrow-data 56.2.0",
+ "arrow-schema 56.2.0",
  "arrow-select",
 ]
 
@@ -427,35 +471,44 @@ version = "56.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "df9c9423c9e71abd1b08a7f788fcd203ba2698ac8e72a1f236f1faa1a06a7414"
 dependencies = [
- "arrow-array",
- "arrow-buffer",
- "arrow-data",
- "arrow-schema",
+ "arrow-array 56.2.0",
+ "arrow-buffer 56.2.0",
+ "arrow-data 56.2.0",
+ "arrow-schema 56.2.0",
  "half",
 ]
 
 [[package]]
 name = "arrow-schema"
-version = "56.0.0"
+version = "56.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "85fa1babc4a45fdc64a92175ef51ff00eba5ebbc0007962fecf8022ac1c6ce28"
+checksum = "b3aa9e59c611ebc291c28582077ef25c97f1975383f1479b12f3b9ffee2ffabe"
 dependencies = [
  "bitflags",
  "serde",
  "serde_json",
 ]
 
+[[package]]
+name = "arrow-schema"
+version = "57.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "d27609cd7dd45f006abae27995c2729ef6f4b9361cde1ddd019dc31a5aa017e0"
+dependencies = [
+ "bitflags",
+]
+
 [[package]]
 name = "arrow-select"
-version = "56.0.0"
+version = "56.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "d8854d15f1cf5005b4b358abeb60adea17091ff5bdd094dca5d3f73787d81170"
+checksum = "8c41dbbd1e97bfcaee4fcb30e29105fb2c75e4d82ae4de70b792a5d3f66b2e7a"
 dependencies = [
  "ahash",
- "arrow-array",
- "arrow-buffer",
- "arrow-data",
- "arrow-schema",
+ "arrow-array 56.2.0",
+ "arrow-buffer 56.2.0",
+ "arrow-data 56.2.0",
+ "arrow-schema 56.2.0",
  "num",
 ]
 
@@ -465,10 +518,10 @@ version = "56.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "2c477e8b89e1213d5927a2a84a72c384a9bf4dd0dbf15f9fd66d821aafd9e95e"
 dependencies = [
- "arrow-array",
- "arrow-buffer",
- "arrow-data",
- "arrow-schema",
+ "arrow-array 56.2.0",
+ "arrow-buffer 56.2.0",
+ "arrow-data 56.2.0",
+ "arrow-schema 56.2.0",
  "arrow-select",
  "memchr",
  "num",
@@ -1579,7 +1632,7 @@ checksum = 
"2af15bb3c6ffa33011ef579f6b0bcbe7c26584688bd6c994f548e44df67f011a"
 dependencies = [
  "arrow",
  "arrow-ipc",
- "arrow-schema",
+ "arrow-schema 56.2.0",
  "async-trait",
  "bytes",
  "bzip2 0.6.1",
@@ -1927,7 +1980,7 @@ checksum = 
"25ddb7c4e645df080c27dad13a198d191da328dd1c98e198664a7a0f64b335cc"
 dependencies = [
  "abi_stable",
  "arrow",
- "arrow-schema",
+ "arrow-schema 56.2.0",
  "async-ffi",
  "async-trait",
  "datafusion",
@@ -1948,7 +2001,7 @@ source = 
"registry+https://github.com/rust-lang/crates.io-index";
 checksum = "7de2782136bd6014670fd84fe3b0ca3b3e4106c96403c3ae05c0598577139977"
 dependencies = [
  "arrow",
- "arrow-buffer",
+ "arrow-buffer 56.2.0",
  "base64",
  "blake2",
  "blake3",
@@ -2182,7 +2235,7 @@ dependencies = [
  "ahash",
  "arrow",
  "arrow-ord",
- "arrow-schema",
+ "arrow-schema 56.2.0",
  "async-trait",
  "chrono",
  "datafusion-common",
@@ -2238,7 +2291,7 @@ source = 
"registry+https://github.com/rust-lang/crates.io-index";
 checksum = "cd1e59e2ca14fe3c30f141600b10ad8815e2856caa59ebbd0e3e07cd3d127a65"
 dependencies = [
  "arrow",
- "arrow-schema",
+ "arrow-schema 56.2.0",
  "datafusion-common",
  "datafusion-datasource",
  "datafusion-expr-common",
@@ -3863,12 +3916,12 @@ source = 
"registry+https://github.com/rust-lang/crates.io-index";
 checksum = "c7288a07ed5d25939a90f9cb1ca5afa6855faa08ec7700613511ae64bdb0620c"
 dependencies = [
  "ahash",
- "arrow-array",
- "arrow-buffer",
+ "arrow-array 56.2.0",
+ "arrow-buffer 56.2.0",
  "arrow-cast",
- "arrow-data",
+ "arrow-data 56.2.0",
  "arrow-ipc",
- "arrow-schema",
+ "arrow-schema 56.2.0",
  "arrow-select",
  "base64",
  "brotli",
@@ -4762,8 +4815,8 @@ name = "sedona"
 version = "0.3.0"
 dependencies = [
  "abi_stable",
- "arrow-array",
- "arrow-schema",
+ "arrow-array 56.2.0",
+ "arrow-schema 56.2.0",
  "async-trait",
  "aws-config",
  "aws-credential-types",
@@ -4807,8 +4860,8 @@ version = "0.3.0"
 dependencies = [
  "adbc_core",
  "adbc_ffi",
- "arrow-array",
- "arrow-schema",
+ "arrow-array 56.2.0",
+ "arrow-schema 56.2.0",
  "datafusion",
  "futures",
  "sedona",
@@ -4847,8 +4900,8 @@ dependencies = [
 name = "sedona-datasource"
 version = "0.3.0"
 dependencies = [
- "arrow-array",
- "arrow-schema",
+ "arrow-array 56.2.0",
+ "arrow-schema 56.2.0",
  "async-trait",
  "datafusion",
  "datafusion-catalog",
@@ -4871,7 +4924,7 @@ dependencies = [
 name = "sedona-expr"
 version = "0.3.0"
 dependencies = [
- "arrow-schema",
+ "arrow-schema 56.2.0",
  "datafusion-common",
  "datafusion-expr",
  "datafusion-physical-expr",
@@ -4889,8 +4942,8 @@ dependencies = [
 name = "sedona-extension"
 version = "0.3.0"
 dependencies = [
- "arrow-array",
- "arrow-schema",
+ "arrow-array 56.2.0",
+ "arrow-schema 56.2.0",
  "datafusion-common",
  "datafusion-expr",
  "libc",
@@ -4904,9 +4957,9 @@ dependencies = [
 name = "sedona-functions"
 version = "0.3.0"
 dependencies = [
- "arrow-array",
+ "arrow-array 56.2.0",
  "arrow-json",
- "arrow-schema",
+ "arrow-schema 56.2.0",
  "criterion",
  "datafusion",
  "datafusion-common",
@@ -4917,6 +4970,7 @@ dependencies = [
  "sedona-expr",
  "sedona-geometry",
  "sedona-schema",
+ "sedona-serde",
  "sedona-testing",
  "serde_json",
  "tokio",
@@ -4928,8 +4982,8 @@ dependencies = [
 name = "sedona-geo"
 version = "0.3.0"
 dependencies = [
- "arrow-array",
- "arrow-schema",
+ "arrow-array 56.2.0",
+ "arrow-schema 56.2.0",
  "criterion",
  "datafusion-common",
  "datafusion-expr",
@@ -4988,8 +5042,8 @@ dependencies = [
 name = "sedona-geoarrow-c"
 version = "0.3.0"
 dependencies = [
- "arrow-array",
- "arrow-schema",
+ "arrow-array 56.2.0",
+ "arrow-schema 56.2.0",
  "cc",
  "criterion",
  "datafusion-common",
@@ -5025,8 +5079,8 @@ dependencies = [
 name = "sedona-geoparquet"
 version = "0.3.0"
 dependencies = [
- "arrow-array",
- "arrow-schema",
+ "arrow-array 56.2.0",
+ "arrow-schema 56.2.0",
  "async-trait",
  "bytes",
  "chrono",
@@ -5062,8 +5116,8 @@ dependencies = [
 name = "sedona-geos"
 version = "0.3.0"
 dependencies = [
- "arrow-array",
- "arrow-schema",
+ "arrow-array 56.2.0",
+ "arrow-schema 56.2.0",
  "byteorder",
  "criterion",
  "datafusion-common",
@@ -5086,8 +5140,8 @@ dependencies = [
 name = "sedona-libgpuspatial"
 version = "0.3.0"
 dependencies = [
- "arrow-array",
- "arrow-schema",
+ "arrow-array 56.2.0",
+ "arrow-schema 56.2.0",
  "bindgen",
  "cmake",
  "log",
@@ -5104,8 +5158,8 @@ name = "sedona-proj"
 version = "0.3.0"
 dependencies = [
  "approx",
- "arrow-array",
- "arrow-schema",
+ "arrow-array 56.2.0",
+ "arrow-schema 56.2.0",
  "cc",
  "criterion",
  "datafusion-common",
@@ -5129,9 +5183,9 @@ name = "sedona-raster"
 version = "0.3.0"
 dependencies = [
  "approx",
- "arrow-array",
- "arrow-buffer",
- "arrow-schema",
+ "arrow-array 56.2.0",
+ "arrow-buffer 56.2.0",
+ "arrow-schema 56.2.0",
  "sedona-common",
  "sedona-schema",
  "sedona-testing",
@@ -5141,9 +5195,9 @@ dependencies = [
 name = "sedona-raster-functions"
 version = "0.3.0"
 dependencies = [
- "arrow-array",
- "arrow-buffer",
- "arrow-schema",
+ "arrow-array 56.2.0",
+ "arrow-buffer 56.2.0",
+ "arrow-schema 56.2.0",
  "criterion",
  "datafusion-common",
  "datafusion-expr",
@@ -5160,8 +5214,8 @@ dependencies = [
 name = "sedona-s2geography"
 version = "0.3.0"
 dependencies = [
- "arrow-array",
- "arrow-schema",
+ "arrow-array 56.2.0",
+ "arrow-schema 56.2.0",
  "cmake",
  "criterion",
  "datafusion-common",
@@ -5182,20 +5236,30 @@ dependencies = [
 name = "sedona-schema"
 version = "0.3.0"
 dependencies = [
- "arrow-array",
- "arrow-schema",
+ "arrow-array 56.2.0",
+ "arrow-schema 56.2.0",
  "datafusion-common",
  "sedona-common",
  "serde_json",
 ]
 
+[[package]]
+name = "sedona-serde"
+version = "0.3.0"
+dependencies = [
+ "arrow-array 56.2.0",
+ "byteorder",
+ "datafusion-common",
+ "wkt 0.14.0",
+]
+
 [[package]]
 name = "sedona-spatial-join"
 version = "0.3.0"
 dependencies = [
  "arrow",
- "arrow-array",
- "arrow-schema",
+ "arrow-array 56.2.0",
+ "arrow-schema 56.2.0",
  "criterion",
  "datafusion",
  "datafusion-common",
@@ -5235,9 +5299,9 @@ dependencies = [
 name = "sedona-testing"
 version = "0.3.0"
 dependencies = [
- "arrow-array",
+ "arrow-array 56.2.0",
  "arrow-cast",
- "arrow-schema",
+ "arrow-schema 56.2.0",
  "criterion",
  "datafusion-common",
  "datafusion-expr",
@@ -5262,8 +5326,8 @@ dependencies = [
 name = "sedona-tg"
 version = "0.3.0"
 dependencies = [
- "arrow-array",
- "arrow-schema",
+ "arrow-array 56.2.0",
+ "arrow-schema 56.2.0",
  "cc",
  "criterion",
  "datafusion-common",
@@ -5284,8 +5348,8 @@ name = "sedonadb"
 version = "0.3.0"
 dependencies = [
  "adbc_core",
- "arrow-array",
- "arrow-schema",
+ "arrow-array 56.2.0",
+ "arrow-schema 56.2.0",
  "async-trait",
  "datafusion",
  "datafusion-common",
@@ -5312,8 +5376,8 @@ dependencies = [
 name = "sedonadbr"
 version = "0.3.0"
 dependencies = [
- "arrow-array",
- "arrow-schema",
+ "arrow-array 56.2.0",
+ "arrow-schema 56.2.0",
  "datafusion",
  "datafusion-common",
  "datafusion-expr",
diff --git a/Cargo.toml b/Cargo.toml
index 9780fbe1..def576c1 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -39,6 +39,7 @@ members = [
     "rust/sedona-schema",
     "rust/sedona-spatial-join",
     "rust/sedona-testing",
+    "rust/sedona-serde",
     "rust/sedona",
     "sedona-cli",
 ]
diff --git a/rust/sedona-functions/Cargo.toml b/rust/sedona-functions/Cargo.toml
index 57afd240..393aaf5a 100644
--- a/rust/sedona-functions/Cargo.toml
+++ b/rust/sedona-functions/Cargo.toml
@@ -48,6 +48,7 @@ sedona-common = { workspace = true }
 sedona-expr = { workspace = true }
 sedona-geometry = { workspace = true }
 sedona-schema = { workspace = true }
+sedona-serde = { path = "../sedona-serde" }
 wkb = { workspace = true }
 wkt = { workspace = true }
 serde_json = { workspace = true }
diff --git a/rust/sedona-functions/src/fixtures/crs_point.sedona 
b/rust/sedona-functions/src/fixtures/crs_point.sedona
new file mode 100644
index 00000000..e534b3a2
--- /dev/null
+++ b/rust/sedona-functions/src/fixtures/crs_point.sedona
@@ -0,0 +1,11 @@
+// Point XY with CRS EPSG:4326
+19
+
+// CRS EPSG:4326
+0 16 230
+
+// number of coordinates
+1 0 0 0
+
+// coordinates (2 doubles per coordinate)
+0 0 0 0 0 0 240 63 0 0 0 0 0 0 240 63
\ No newline at end of file
diff --git 
a/rust/sedona-functions/src/fixtures/empty_geometry_collection.sedona 
b/rust/sedona-functions/src/fixtures/empty_geometry_collection.sedona
new file mode 100644
index 00000000..39dca86b
--- /dev/null
+++ b/rust/sedona-functions/src/fixtures/empty_geometry_collection.sedona
@@ -0,0 +1,5 @@
+114
+
+0 0 0
+
+0 0 0 0
\ No newline at end of file
diff --git a/rust/sedona-functions/src/fixtures/empty_linestring.sedona 
b/rust/sedona-functions/src/fixtures/empty_linestring.sedona
new file mode 100644
index 00000000..68e7aed8
--- /dev/null
+++ b/rust/sedona-functions/src/fixtures/empty_linestring.sedona
@@ -0,0 +1,5 @@
+34
+
+0 0 0
+
+0 0 0 0
\ No newline at end of file
diff --git a/rust/sedona-functions/src/fixtures/empty_multilinestring.sedona 
b/rust/sedona-functions/src/fixtures/empty_multilinestring.sedona
new file mode 100644
index 00000000..085f9d52
--- /dev/null
+++ b/rust/sedona-functions/src/fixtures/empty_multilinestring.sedona
@@ -0,0 +1,5 @@
+82
+
+0 0 0
+
+0 0 0 0 0 0 0 0
\ No newline at end of file
diff --git a/rust/sedona-functions/src/fixtures/empty_multipolygon.sedona 
b/rust/sedona-functions/src/fixtures/empty_multipolygon.sedona
new file mode 100644
index 00000000..559c5a3d
--- /dev/null
+++ b/rust/sedona-functions/src/fixtures/empty_multipolygon.sedona
@@ -0,0 +1,5 @@
+98
+
+0 0 0
+
+0 0 0 0 0 0 0 0
\ No newline at end of file
diff --git a/rust/sedona-functions/src/fixtures/empty_point.sedona 
b/rust/sedona-functions/src/fixtures/empty_point.sedona
new file mode 100644
index 00000000..5ab2f596
--- /dev/null
+++ b/rust/sedona-functions/src/fixtures/empty_point.sedona
@@ -0,0 +1,5 @@
+18
+
+0 0 0
+
+0 0 0 0
\ No newline at end of file
diff --git a/rust/sedona-functions/src/fixtures/empty_polygon.sedona 
b/rust/sedona-functions/src/fixtures/empty_polygon.sedona
new file mode 100644
index 00000000..3acc9bc3
--- /dev/null
+++ b/rust/sedona-functions/src/fixtures/empty_polygon.sedona
@@ -0,0 +1,5 @@
+50
+
+0 0 0
+
+0 0 0 0
\ No newline at end of file
diff --git a/rust/sedona-functions/src/fixtures/geometrycollection.sedona 
b/rust/sedona-functions/src/fixtures/geometrycollection.sedona
new file mode 100644
index 00000000..3918cbaf
--- /dev/null
+++ b/rust/sedona-functions/src/fixtures/geometrycollection.sedona
@@ -0,0 +1,42 @@
+// metadata GeometryCollection XY NO SRID
+114
+
+// missing srid information
+0 0 0
+
+// number of geometries
+3 0 0 0
+
+// point geometry
+18
+
+0 0 0
+
+1 0 0 0
+
+0 0 0 0 0 0 16 64 0 0 0 0 0 0 24 64 
+      
+// linestring geometry
+34
+
+0 0 0
+
+2 0 0 0
+
+0 0 0 0 0 0 16 64 0 0 0 0 0 0 24 64
+0 0 0 0 0 0 28 64 0 0 0 0 0 0 36 64
+
+// polygon geometry
+50
+
+0 0 0
+
+4 0 0 0
+
+0 0 0 0 0 0 16 64 0 0 0 0 0 0 24 64
+0 0 0 0 0 0 28 64 0 0 0 0 0 0 36 64
+0 0 0 0 0 0 16 64 0 0 0 0 0 0 36 64
+0 0 0 0 0 0 16 64 0 0 0 0 0 0 24 64
+
+1 0 0 0
+4 0 0 0 
\ No newline at end of file
diff --git 
a/rust/sedona-functions/src/fixtures/geometrycollectioncomplex.sedona 
b/rust/sedona-functions/src/fixtures/geometrycollectioncomplex.sedona
new file mode 100644
index 00000000..6dfb04c8
--- /dev/null
+++ b/rust/sedona-functions/src/fixtures/geometrycollectioncomplex.sedona
@@ -0,0 +1,52 @@
+// // metadata GeometryCollection XY NO SRID
+114
+
+// missing srid information
+0 0 0
+
+// number of geometries
+4 0 0 0
+
+// point geometry
+18
+
+0 0 0
+
+1 0 0 0
+
+0 0 0 0 0 0 16 64 0 0 0 0 0 0 24 64
+
+// linestring geometry
+34
+
+0 0 0
+
+2 0 0 0
+
+0 0 0 0 0 0 16 64 0 0 0 0 0 0 24 64
+0 0 0 0 0 0 28 64 0 0 0 0 0 0 36 64
+
+// polygon geometry
+50
+
+0 0 0
+
+4 0 0 0
+
+0 0 0 0 0 0 16 64 0 0 0 0 0 0 24 64
+0 0 0 0 0 0 28 64 0 0 0 0 0 0 36 64
+0 0 0 0 0 0 16 64 0 0 0 0 0 0 36 64
+0 0 0 0 0 0 16 64 0 0 0 0 0 0 24 64
+
+1 0 0 0
+4 0 0 0
+
+// multipoint geometry
+66
+
+0 0 0
+
+2 0 0 0
+
+0 0 0 0 0 0 240 63 0 0 0 0 0 0 0 64
+0 0 0 0 0 0 8 64 0 0 0 0 0 0 16 64
\ No newline at end of file
diff --git a/rust/sedona-functions/src/fixtures/linestring.sedona 
b/rust/sedona-functions/src/fixtures/linestring.sedona
new file mode 100644
index 00000000..02e1ba01
--- /dev/null
+++ b/rust/sedona-functions/src/fixtures/linestring.sedona
@@ -0,0 +1,13 @@
+// metadata LINESTRING XY NO SRID
+34
+
+// missing srid information
+0 0 0
+
+// number of coordinates
+3 0 0 0
+
+// coordinates (2 doubles per coordinate)
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 240 63 0 0 0 0 0 0 240 63
+0 0 0 0 0 0 0 64 0 0 0 0 0 0 0 64
\ No newline at end of file
diff --git a/rust/sedona-functions/src/fixtures/multilinestring.sedona 
b/rust/sedona-functions/src/fixtures/multilinestring.sedona
new file mode 100644
index 00000000..22466c88
--- /dev/null
+++ b/rust/sedona-functions/src/fixtures/multilinestring.sedona
@@ -0,0 +1,25 @@
+// metadata MultiLinestring XY NO SRID
+82
+
+// missing srid information
+0 0 0
+
+// number of points
+4 0 0 0
+
+// coordinates linestring 1
+0 0 0 0 0 0 240 63 0 0 0 0 0 0 240 63
+0 0 0 0 0 0 0 64 0 0 0 0 0 0 0 64
+
+// coordinates linestring 2
+0 0 0 0 0 0 16 64 0 0 0 0 0 0 20 64
+0 0 0 0 0 0 24 64 0 0 0 0 0 0 28 64
+
+// number of linestrings
+2 0 0 0
+
+// linestring 1 has 2 points
+2 0 0 0
+
+// linestring 2 has 2 points
+2 0 0 0
\ No newline at end of file
diff --git a/rust/sedona-functions/src/fixtures/multipoint.sedona 
b/rust/sedona-functions/src/fixtures/multipoint.sedona
new file mode 100644
index 00000000..256068cb
--- /dev/null
+++ b/rust/sedona-functions/src/fixtures/multipoint.sedona
@@ -0,0 +1,13 @@
+// metadata Multipoint XY NO SRID
+66
+
+// missing srid information
+0 0 0
+
+// number of points
+3 0 0 0
+
+// coordinates (2 doubles per point)
+0 0 0 0 0 0 240 63 0 0 0 0 0 0 240 63
+0 0 0 0 0 0 0 64 0 0 0 0 0 0 0 64
+0 0 0 0 0 0 16 64 0 0 0 0 0 0 20 64
\ No newline at end of file
diff --git a/rust/sedona-functions/src/fixtures/multipoint_empty.sedona 
b/rust/sedona-functions/src/fixtures/multipoint_empty.sedona
new file mode 100644
index 00000000..f11bc982
--- /dev/null
+++ b/rust/sedona-functions/src/fixtures/multipoint_empty.sedona
@@ -0,0 +1,5 @@
+66
+
+0 0 0
+
+0 0 0 0
\ No newline at end of file
diff --git a/rust/sedona-functions/src/fixtures/multipolygon.sedona 
b/rust/sedona-functions/src/fixtures/multipolygon.sedona
new file mode 100644
index 00000000..562aa70c
--- /dev/null
+++ b/rust/sedona-functions/src/fixtures/multipolygon.sedona
@@ -0,0 +1,65 @@
+// metadata Multipolygon XY NO SRID
+98
+
+// missing srid information
+0 0 0
+
+// number of points
+30 0 0 0
+
+// polygon 1 coordinates
+0 0 0 0 0 0 240 63 0 0 0 0 0 0 240 63
+0 0 0 0 0 0 36 64 0 0 0 0 0 0 240 63
+0 0 0 0 0 0 36 64 0 0 0 0 0 0 36 64
+0 0 0 0 0 0 240 63 0 0 0 0 0 0 36 64
+0 0 0 0 0 0 240 63 0 0 0 0 0 0 240 63
+
+0 0 0 0 0 0 0 64 0 0 0 0 0 0 0 64
+0 0 0 0 0 0 16 64 0 0 0 0 0 0 0 64
+0 0 0 0 0 0 16 64 0 0 0 0 0 0 16 64
+0 0 0 0 0 0 0 64 0 0 0 0 0 0 16 64
+0 0 0 0 0 0 0 64 0 0 0 0 0 0 0 64
+
+0 0 0 0 0 0 24 64 0 0 0 0 0 0 24 64
+0 0 0 0 0 0 32 64 0 0 0 0 0 0 24 64
+0 0 0 0 0 0 32 64 0 0 0 0 0 0 32 64
+0 0 0 0 0 0 24 64 0 0 0 0 0 0 32 64
+0 0 0 0 0 0 24 64 0 0 0 0 0 0 24 64
+
+// polygon 2 coordinates
+0 0 0 0 0 0 40 64 0 0 0 0 0 0 240 63
+0 0 0 0 0 0 52 64 0 0 0 0 0 0 240 63
+0 0 0 0 0 0 52 64 0 0 0 0 0 0 34 64
+0 0 0 0 0 0 40 64 0 0 0 0 0 0 34 64
+0 0 0 0 0 0 40 64 0 0 0 0 0 0 240 63
+
+0 0 0 0 0 0 42 64 0 0 0 0 0 0 0 64
+0 0 0 0 0 0 46 64 0 0 0 0 0 0 0 64
+0 0 0 0 0 0 46 64 0 0 0 0 0 0 16 64
+0 0 0 0 0 0 42 64 0 0 0 0 0 0 16 64
+0 0 0 0 0 0 42 64 0 0 0 0 0 0 0 64
+
+0 0 0 0 0 0 49 64 0 0 0 0 0 0 20 64
+0 0 0 0 0 0 51 64 0 0 0 0 0 0 20 64
+0 0 0 0 0 0 51 64 0 0 0 0 0 0 28 64
+0 0 0 0 0 0 49 64 0 0 0 0 0 0 28 64
+0 0 0 0 0 0 49 64 0 0 0 0 0 0 20 64
+
+// number of polygons
+2 0 0 0
+
+// number of polygon 1 components
+3 0 0 0
+
+// number of points in polygon 1 components
+5 0 0 0
+5 0 0 0
+5 0 0 0
+
+// number of polygon 2 components
+3 0 0 0
+
+// number of points in polygon 2 components
+5 0 0 0
+5 0 0 0
+5 0 0 0
\ No newline at end of file
diff --git 
a/rust/sedona-functions/src/fixtures/nested_geometry_collection.sedona 
b/rust/sedona-functions/src/fixtures/nested_geometry_collection.sedona
new file mode 100644
index 00000000..1bb0f57d
--- /dev/null
+++ b/rust/sedona-functions/src/fixtures/nested_geometry_collection.sedona
@@ -0,0 +1,46 @@
+// metadata GeometryCollection XY NO SRID
+114
+
+0 0 0
+
+2 0 0 0
+
+// point geometry
+18
+
+0 0 0
+
+1 0 0 0
+
+0 0 0 0 0 0 240 63 0 0 0 0 0 0 240 63
+
+// geometry collection geometry
+114 0 0 0
+
+2 0 0 0
+
+// linestring geometry
+34
+
+0 0 0
+
+2 0 0 0
+
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 240 63 0 0 0 0 0 0 240 63
+
+// polygon geometry
+50
+
+0 0 0
+
+5 0 0 0
+
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 64 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 64 0 0 0 0 0 0 0 64
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 64
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+
+1 0 0 0
+5 0 0 0
\ No newline at end of file
diff --git a/rust/sedona-functions/src/fixtures/point.sedona 
b/rust/sedona-functions/src/fixtures/point.sedona
new file mode 100644
index 00000000..94e872a1
--- /dev/null
+++ b/rust/sedona-functions/src/fixtures/point.sedona
@@ -0,0 +1,11 @@
+// metadata POINT XY NO SRID
+18
+
+// srid information
+0 0 0
+
+// number of coordinates
+1 0 0 0
+
+// coordinates (2 doubles per coordinate)
+0 0 0 0 0 0 240 63 0 0 0 0 0 0 240 63
\ No newline at end of file
diff --git a/rust/sedona-functions/src/fixtures/point_float_coords.sedona 
b/rust/sedona-functions/src/fixtures/point_float_coords.sedona
new file mode 100644
index 00000000..a75f94d0
--- /dev/null
+++ b/rust/sedona-functions/src/fixtures/point_float_coords.sedona
@@ -0,0 +1,42 @@
+50
+
+0 0 0
+
+11 0 0 0
+
+59 111 47 211 252 176 40 64
+243 214 83 60 230 214 70 64
+
+164 49 237 31 240 116 55 64
+235 19 96 200 247 248 80 64
+
+131 251 161 159 176 72 65 64
+228 105 70 91 254 100 76 64
+
+243 214 83 60 230 214 70 64
+131 251 161 159 176 72 65 64
+
+81 184 200 34 101 224 61 64
+157 183 151 105 126 88 54 64
+
+59 111 47 211 252 176 40 64
+243 214 83 60 230 214 70 64
+
+149 70 55 221 154 31 57 64
+59 111 240 116 107 254 70 64
+
+118 222 224 233 214 252 62 64
+75 163 155 110 205 15 73 64
+
+210 152 246 15 120 186 65 64
+210 152 246 15 120 186 70 64
+
+31 197 40 164 12 60 62 64
+59 111 240 116 107 126 68 64
+
+149 70 55 221 154 31 57 64
+59 111 240 116 107 254 70 64
+
+2 0 0 0
+6 0 0 0
+5 0 0 0
diff --git a/rust/sedona-functions/src/fixtures/polygon.sedona 
b/rust/sedona-functions/src/fixtures/polygon.sedona
new file mode 100644
index 00000000..7a2ab605
--- /dev/null
+++ b/rust/sedona-functions/src/fixtures/polygon.sedona
@@ -0,0 +1,41 @@
+// metadata Polygon XY NO SRID
+50
+
+// no srid
+0 0 0
+
+// number of points
+15 0 0 0
+
+// polygon 1 ring 1
+0 0 0 0 0 0 240 63 0 0 0 0 0 0 240 63
+0 0 0 0 0 0 36 64 0 0 0 0 0 0 240 63
+0 0 0 0 0 0 36 64 0 0 0 0 0 0 36 64
+0 0 0 0 0 0 240 63 0 0 0 0 0 0 36 64
+0 0 0 0 0 0 240 63 0 0 0 0 0 0 240 63
+
+// hole 1 ring 1
+0 0 0 0 0 0 0 64 0 0 0 0 0 0 0 64
+0 0 0 0 0 0 16 64 0 0 0 0 0 0 0 64
+0 0 0 0 0 0 16 64 0 0 0 0 0 0 16 64
+0 0 0 0 0 0 0 64 0 0 0 0 0 0 16 64
+0 0 0 0 0 0 0 64 0 0 0 0 0 0 0 64
+
+// hole 2 ring 1
+0 0 0 0 0 0 24 64 0 0 0 0 0 0 24 64
+0 0 0 0 0 0 32 64 0 0 0 0 0 0 24 64
+0 0 0 0 0 0 32 64 0 0 0 0 0 0 32 64
+0 0 0 0 0 0 24 64 0 0 0 0 0 0 32 64
+0 0 0 0 0 0 24 64 0 0 0 0 0 0 24 64
+
+// number of rings
+3 0 0 0
+
+// number of points internal 1
+5 0 0 0
+
+// number of points hole 1
+5 0 0 0
+
+// number of points hole 2
+5 0 0 0
\ No newline at end of file
diff --git a/rust/sedona-functions/src/lib.rs b/rust/sedona-functions/src/lib.rs
index 44c8ad02..9eec6398 100644
--- a/rust/sedona-functions/src/lib.rs
+++ b/rust/sedona-functions/src/lib.rs
@@ -67,3 +67,4 @@ pub mod st_union_agg;
 mod st_xyzm;
 mod st_xyzm_minmax;
 mod st_zmflag;
+mod st_from_sedona_spark;
diff --git a/rust/sedona-functions/src/register.rs 
b/rust/sedona-functions/src/register.rs
index ff439578..e9bc4a14 100644
--- a/rust/sedona-functions/src/register.rs
+++ b/rust/sedona-functions/src/register.rs
@@ -120,6 +120,7 @@ pub fn default_function_set() -> FunctionSet {
         crate::st_xyzm::st_y_udf,
         crate::st_xyzm::st_z_udf,
         crate::st_zmflag::st_zmflag_udf,
+        crate::st_from_sedona_spark::st_geomfromsedona_udf,
     );
 
     register_aggregate_udfs!(
diff --git a/rust/sedona-functions/src/st_from_sedona_spark.rs 
b/rust/sedona-functions/src/st_from_sedona_spark.rs
new file mode 100644
index 00000000..b96b4bb7
--- /dev/null
+++ b/rust/sedona-functions/src/st_from_sedona_spark.rs
@@ -0,0 +1,387 @@
+use crate::executor::WkbExecutor;
+use arrow_array::builder::BinaryBuilder;
+use arrow_schema::DataType;
+use datafusion_common::cast::as_binary_array;
+use datafusion_common::ScalarValue;
+use datafusion_expr::scalar_doc_sections::DOC_SECTION_OTHER;
+use datafusion_expr::{ColumnarValue, Documentation, Volatility};
+use sedona_expr::scalar_udf::{SedonaScalarKernel, SedonaScalarUDF};
+use sedona_geometry::wkb_factory::WKB_MIN_PROBABLE_BYTES;
+use sedona_schema::crs::{deserialize_crs, Crs};
+use sedona_schema::datatypes::{Edges, SedonaType, WKB_GEOGRAPHY, WKB_GEOMETRY};
+use sedona_schema::matchers::ArgMatcher;
+use sedona_serde::deserialize::deserialize;
+use std::any::Any;
+use std::io::{Read, Seek};
+use std::sync::Arc;
+
+fn to_crs_str(scalar_arg: &ScalarValue) -> Option<String> {
+    if let Ok(ScalarValue::Utf8(Some(crs))) = 
scalar_arg.cast_to(&DataType::Utf8) {
+        if crs.chars().all(|c| c.is_ascii_digit()) {
+            return Some(format!("EPSG:{crs}"));
+        } else {
+            return Some(crs);
+        }
+    }
+
+    None
+}
+
+#[derive(Debug)]
+struct STGeomFromSedona {
+    out_type: SedonaType,
+}
+
+pub fn st_geomfromsedona_udf() -> SedonaScalarUDF {
+    let kernel = Arc::new(STGeomFromSedona {
+        out_type: WKB_GEOMETRY,
+    });
+
+    SedonaScalarUDF::new(
+        "st_geomfromsedona",
+        vec![kernel],
+        Volatility::Immutable,
+        None,
+    )
+}
+
+impl SedonaScalarKernel for STGeomFromSedona {
+    fn return_type(&self, args: &[SedonaType]) -> 
datafusion_common::Result<Option<SedonaType>> {
+        let matcher = ArgMatcher::new(
+            vec![ArgMatcher::is_binary(), ArgMatcher::is_string()],
+            self.out_type.clone(),
+        );
+
+        matcher.match_args(args)
+    }
+
+    fn return_type_from_args_and_scalars(
+        &self,
+        args: &[SedonaType],
+        _scalar_args: &[Option<&ScalarValue>],
+    ) -> datafusion_common::Result<Option<SedonaType>> {
+        let matcher = ArgMatcher::new(
+            vec![ArgMatcher::is_geometry(), ArgMatcher::is_string()],
+            self.out_type.clone(),
+        );
+
+        if !matcher.matches(args) {
+            return Ok(None);
+        }
+
+        let crs_scalar = _scalar_args.get(1).unwrap();
+
+        let crs_str_opt = if let Some(scalar_crs) = crs_scalar {
+            to_crs_str(scalar_crs)
+        } else {
+            None
+        };
+
+        match crs_str_opt {
+            Some(to_crs) => {
+                let val = serde_json::Value::String(to_crs.to_string());
+                let crs = deserialize_crs(&val)?;
+                Ok(Some(SedonaType::Wkb(Edges::Planar, crs)))
+            }
+            _ => Ok(Some(SedonaType::Wkb(Edges::Planar, None))),
+        }
+    }
+
+    fn invoke_batch(
+        &self,
+        arg_types: &[SedonaType],
+        args: &[ColumnarValue],
+    ) -> datafusion_common::Result<ColumnarValue> {
+        let executor = WkbExecutor::new(arg_types, args);
+        let arg_array = args[0]
+            .cast_to(&DataType::Binary, None)?
+            .to_array(executor.num_iterations())?;
+
+        let mut builder = BinaryBuilder::with_capacity(
+            executor.num_iterations(),
+            WKB_MIN_PROBABLE_BYTES * executor.num_iterations(),
+        );
+
+        for item in as_binary_array(&arg_array)? {
+            if let Some(sedona_bytes) = item {
+                deserialize(&mut builder, sedona_bytes)?;
+                builder.append_value(vec![]);
+            }
+        }
+
+        let new_array = builder.finish();
+        executor.finish(Arc::new(new_array))
+    }
+}
+
+fn doc(name: &str, out_type_name: &str) -> Documentation {
+    Documentation::builder(
+        DOC_SECTION_OTHER,
+        format!("Construct a {out_type_name} from Sedona internal geometry 
representation."),
+        format!("{name} (geom: Binary)"),
+    )
+    .with_argument(
+        "geom",
+        format!(
+            "Binary: Sedona representation of the {}",
+            out_type_name.to_lowercase()
+        ),
+    )
+    .with_sql_example(format!("SELECT {name}('SedonaBinary')"))
+    .with_related_udf("ST_FromSedona")
+    .build()
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use sedona_testing::testers::ScalarUdfTester;
+
+    fn get_tester() -> ScalarUdfTester {
+        ScalarUdfTester::new(
+            st_geomfromsedona_udf().into(),
+            vec![
+                SedonaType::Wkb(Edges::Planar, Crs::None),
+                SedonaType::Arrow(DataType::Utf8),
+            ],
+        )
+    }
+
+    fn fixture_to_bytes(wkb: &str) -> Vec<u8> {
+        wkb.split("\n")
+            .filter(|line| !line.starts_with("//") && !line.is_empty())
+            .flat_map(|s| s.split_whitespace())
+            .map(|num| num.parse::<u8>().expect("invalid byte"))
+            .collect::<Vec<u8>>()
+    }
+
+    #[test]
+    fn test_st_from_sedona_spark_point_1() {
+        let binary_geometry = 
fixture_to_bytes(include_str!("fixtures/point.sedona"));
+        let tester = get_tester();
+
+        let result = tester
+            .invoke_scalar_scalar(binary_geometry, 
ScalarValue::Utf8(Some("4326".to_string())))
+            .unwrap();
+
+        tester.assert_scalar_result_equals(result, "POINT (1 1)");
+    }
+
+    #[test]
+    fn test_st_from_sedona_spark_linestring_1() {
+        let binary_geometry = 
fixture_to_bytes(include_str!("fixtures/linestring.sedona"));
+        let tester = get_tester();
+
+        let result = tester
+            .invoke_scalar_scalar(binary_geometry, 
ScalarValue::Utf8(Some("4326".to_string())))
+            .unwrap();
+
+        tester.assert_scalar_result_equals(result, "LINESTRING (0 0, 1 1, 2 
2)");
+    }
+
+    #[test]
+    fn test_multipoint_geometry() {
+        let binary_geometry = 
fixture_to_bytes(include_str!("fixtures/multipoint.sedona"));
+        let tester = get_tester();
+
+        let result = tester
+            .invoke_scalar_scalar(binary_geometry, 
ScalarValue::Utf8(Some("4326".to_string())))
+            .unwrap();
+
+        tester.assert_scalar_result_equals(result, "MULTIPOINT((1 1), (2 2), 
(4 5))");
+    }
+
+    #[test]
+    fn test_multilinestring_geometry() {
+        let binary_geometry = 
fixture_to_bytes(include_str!("fixtures/multilinestring.sedona"));
+        let tester = get_tester();
+
+        let result = tester
+            .invoke_scalar_scalar(binary_geometry, 
ScalarValue::Utf8(Some("4326".to_string())))
+            .unwrap();
+
+        tester.assert_scalar_result_equals(result, "MULTILINESTRING((1 1, 2 
2), (4 5, 6 7))");
+    }
+
+    #[test]
+    fn test_polygon_geometry() {
+        let binary_geometry = 
fixture_to_bytes(include_str!("fixtures/polygon.sedona"));
+        let tester = get_tester();
+
+        let result = tester
+            .invoke_scalar_scalar(binary_geometry, 
ScalarValue::Utf8(Some("4326".to_string())))
+            .unwrap();
+
+        tester.assert_scalar_result_equals(
+            result,
+            "
+            POLYGON (
+                (1 1, 10 1, 10 10, 1 10, 1 1),
+                (2 2, 4 2, 4 4, 2 4, 2 2),
+                (6 6, 8 6, 8 8, 6 8, 6 6)
+            )",
+        );
+    }
+
+    #[test]
+    fn test_multipolygon_geometry() {
+        let binary_geometry = 
fixture_to_bytes(include_str!("fixtures/multipolygon.sedona"));
+        let tester = get_tester();
+
+        let result = tester
+            .invoke_scalar_scalar(binary_geometry, 
ScalarValue::Utf8(Some("4326".to_string())))
+            .unwrap();
+
+        tester.assert_scalar_result_equals(
+            result,
+            "MULTIPOLYGON (
+                        (
+                            (1 1, 10 1, 10 10, 1 10, 1 1),
+                            (2 2, 4 2, 4 4, 2 4, 2 2),
+                            (6 6, 8 6, 8 8, 6 8, 6 6)
+                        ),
+                         (
+                            (12 1, 20 1, 20 9, 12 9, 12 1),
+                            (13 2, 15 2, 15 4, 13 4, 13 2),
+                            (17 5, 19 5, 19 7, 17 7, 17 5)
+                         )
+                     )",
+        );
+    }
+
+    #[test]
+    fn test_geometrycollection_geometry() {
+        let binary_geometry = 
fixture_to_bytes(include_str!("fixtures/geometrycollection.sedona"));
+        let tester = get_tester();
+
+        let result = tester
+            .invoke_scalar_scalar(binary_geometry, 
ScalarValue::Utf8(Some("4326".to_string())))
+            .unwrap();
+
+        tester.assert_scalar_result_equals(
+            result,
+            "GEOMETRYCOLLECTION(
+                POINT(4 6),
+                LINESTRING(4 6,7 10),
+                POLYGON((4 6,7 10,4 10,4 6))
+             )",
+        );
+    }
+
+    #[test]
+    fn test_complex_geometry_collection() {
+        let binary_geometry =
+            
fixture_to_bytes(include_str!("fixtures/geometrycollectioncomplex.sedona"));
+        let tester = get_tester();
+
+        let result = tester
+            .invoke_scalar_scalar(binary_geometry, 
ScalarValue::Utf8(Some("4326".to_string())))
+            .unwrap();
+
+        tester.assert_scalar_result_equals(
+            result,
+            "GEOMETRYCOLLECTION(
+                        POINT(4 6),
+                        LINESTRING(4 6,7 10),
+                        POLYGON((4 6,7 10,4 10,4 6)),
+                        MULTIPOINT((1 2),(3 4))
+                    )",
+        );
+    }
+
+    #[test]
+    fn test_geometry_collection_in_geometry_collection() {
+        let binary_geometry =
+            
fixture_to_bytes(include_str!("fixtures/nested_geometry_collection.sedona"));
+        let tester = get_tester();
+
+        let result = tester
+            .invoke_scalar_scalar(binary_geometry, 
ScalarValue::Utf8(Some("4326".to_string())))
+            .unwrap();
+
+        tester.assert_scalar_result_equals(
+            result,
+            "GEOMETRYCOLLECTION (
+                        POINT (1 1),
+                        GEOMETRYCOLLECTION (
+                            LINESTRING (0 0, 1 1),
+                            POLYGON ((0 0, 2 0, 2 2, 0 2, 0 0))
+                        )
+                     )",
+        );
+    }
+
+    #[test]
+    fn test_empty_geometries() {
+        let test_data = vec![
+            (include_str!("fixtures/empty_point.sedona"), "POINT EMPTY"),
+            (
+                include_str!("fixtures/multipoint_empty.sedona"),
+                "MULTIPOINT EMPTY",
+            ),
+            (
+                include_str!("fixtures/empty_linestring.sedona"),
+                "LINESTRING EMPTY",
+            ),
+            (
+                include_str!("fixtures/empty_polygon.sedona"),
+                "POLYGON EMPTY",
+            ),
+            (
+                include_str!("fixtures/empty_multipolygon.sedona"),
+                "MULTIPOLYGON EMPTY",
+            ),
+            (
+                include_str!("fixtures/empty_multilinestring.sedona"),
+                "MULTILINESTRING EMPTY",
+            ),
+            (
+                include_str!("fixtures/empty_geometry_collection.sedona"),
+                "GEOMETRYCOLLECTION EMPTY",
+            ),
+        ];
+
+        let tester = get_tester();
+
+        for (test_fixture, expected_wkt) in test_data {
+            let binary_geometry = fixture_to_bytes(test_fixture);
+
+            let result = tester
+                .invoke_scalar_scalar(binary_geometry, 
ScalarValue::Utf8(Some("4326".to_string())))
+                .unwrap();
+
+            tester.assert_scalar_result_equals(result, expected_wkt);
+        }
+    }
+
+    #[test]
+    fn test_non_integer_coordinates() {
+        let binary_geometry = 
fixture_to_bytes(include_str!("fixtures/point_float_coords.sedona"));
+        let tester = get_tester();
+
+        let result = tester
+            .invoke_scalar_scalar(binary_geometry, 
ScalarValue::Utf8(Some("4326".to_string())))
+            .unwrap();
+
+        tester.assert_scalar_result_equals(
+            result,
+        "POLYGON (
+                  (
+                    12.345678901234 45.678901234567,
+                    23.456789012345 67.890123456789,
+                    34.567890123456 56.789012345678,
+                    45.678901234567 34.567890123456,
+                    29.876543210987 22.345678901234,
+                    12.345678901234 45.678901234567
+                  ),
+                  (
+                    25.123456789012 45.987654321098,
+                    30.987654321098 50.123456789012,
+                    35.456789012345 45.456789012345,
+                    30.234567890123 40.987654321098,
+                    25.123456789012 45.987654321098
+                  )
+                )"
+        );
+    }
+}
diff --git a/rust/sedona-functions/Cargo.toml b/rust/sedona-serde/Cargo.toml
similarity index 61%
copy from rust/sedona-functions/Cargo.toml
copy to rust/sedona-serde/Cargo.toml
index 57afd240..7eddb106 100644
--- a/rust/sedona-functions/Cargo.toml
+++ b/rust/sedona-serde/Cargo.toml
@@ -15,11 +15,8 @@
 # specific language governing permissions and limitations
 # under the License.
 [package]
-name = "sedona-functions"
+name = "sedona-serde"
 version.workspace = true
-license.workspace = true
-keywords.workspace = true
-categories.workspace = true
 homepage.workspace = true
 repository.workspace = true
 description.workspace = true
@@ -31,27 +28,9 @@ rust-version.workspace = true
 result_large_err = "allow"
 
 [dev-dependencies]
-arrow-json = { workspace = true }
-criterion = { workspace = true }
-rstest = { workspace = true }
-sedona-testing = { workspace = true, features = ["criterion"] }
-datafusion = { workspace = true }
-tokio = { workspace = true, features = ["rt", "macros"] }
 
 [dependencies]
-arrow-schema = { workspace = true }
 arrow-array = { workspace = true }
 datafusion-common = { workspace = true }
-datafusion-expr = { workspace = true }
-geo-traits = { workspace = true }
-sedona-common = { workspace = true }
-sedona-expr = { workspace = true }
-sedona-geometry = { workspace = true }
-sedona-schema = { workspace = true }
-wkb = { workspace = true }
 wkt = { workspace = true }
-serde_json = { workspace = true }
-
-[[bench]]
-harness = false
-name = "native-functions"
+byteorder = "1.5.0"
diff --git a/rust/sedona-serde/src/deserialize.rs 
b/rust/sedona-serde/src/deserialize.rs
new file mode 100644
index 00000000..a28811ca
--- /dev/null
+++ b/rust/sedona-serde/src/deserialize.rs
@@ -0,0 +1,130 @@
+// 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.
+
+use crate::linestring::{parse_linestring, parse_multilinestring};
+use crate::point::{parse_multipoint, parse_point, write_empty_point};
+use crate::polygon::{parse_multipolygon, parse_polygon, write_empty_polygon};
+use arrow_array::builder::BinaryBuilder;
+use byteorder::{ByteOrder, LittleEndian, ReadBytesExt, WriteBytesExt};
+use datafusion_common::error::DataFusionError;
+use std::io::{Cursor};
+use wkt::types::Dimension;
+
+pub fn deserialize<'a>(builder: &mut BinaryBuilder, bytes: &[u8]) -> 
datafusion_common::Result<()> {
+    use std::io::Cursor;
+
+    if bytes.len() < 8 {
+        return Err(DataFusionError::Internal(
+            "Sedona bytes are too short".to_string(),
+        ));
+    }
+
+    let mut reader = Cursor::new(bytes);
+
+    parse_geometry::<LittleEndian, LittleEndian>(builder, &mut reader, bytes)
+}
+
+pub fn parse_geometry<'a, IN: ByteOrder, OUT: ByteOrder>(
+    builder: &mut BinaryBuilder,
+    cursor: &mut Cursor<&[u8]>,
+    bytes: &[u8],
+) -> datafusion_common::Result<()> {
+    let preamble_byte = cursor.read_u8()? & 0xFF;
+
+    let wkb_type = preamble_byte >> 4;
+
+    let dimension = get_dimension((preamble_byte & 0x0F) >> 1);
+
+    let has_srid = (preamble_byte & 0x01) != 0;
+
+    cursor.set_position(cursor.position() + 3); // Skip 3 bytes
+
+    match wkb_type {
+        1 => {
+            let number_of_coordinates = cursor.read_u32::<IN>()?;
+            if number_of_coordinates == 0 {
+                write_empty_point::<OUT>(builder, dimension)?;
+                return Ok(());
+            }
+
+            parse_point::<IN, OUT>(builder, cursor, dimension)?;
+        }
+        2 => {
+            parse_linestring::<IN, OUT>(builder, cursor, dimension)?;
+        }
+        3 => {
+            let mut meta_data_reader = Cursor::new(bytes);
+
+            let number_of_points = cursor.read_u32::<IN>()?;
+            if number_of_points == 0 {
+                write_empty_polygon::<OUT>(builder, dimension)?;
+
+                return Ok(());
+            }
+
+            let metadata_start_position = number_of_points * 8 * 2;
+            meta_data_reader.set_position(cursor.position() + 
(metadata_start_position) as u64);
+
+            parse_polygon::<IN, OUT>(builder, cursor, &mut meta_data_reader, 
dimension)?;
+            cursor.set_position(meta_data_reader.position());
+        }
+        4 => {
+            parse_multipoint::<IN, OUT>(builder, cursor, dimension)?;
+        }
+        5 => {
+            // let bytes = cursor.into_inner();
+            let mut meta_data_reader = Cursor::new(bytes);
+            parse_multilinestring::<IN, OUT>(builder, cursor, &mut 
meta_data_reader, dimension)?;
+            cursor.set_position(meta_data_reader.position());
+        }
+        6 => {
+            let mut meta_data_reader = Cursor::new(bytes);
+            parse_multipolygon::<IN, OUT>(builder, cursor, &mut 
meta_data_reader, dimension)?;
+            cursor.set_position(meta_data_reader.position());
+        }
+        7 => {
+            let number_of_geometries = cursor.read_u32::<IN>()?;
+            builder.write_i8(1)?;
+            builder.write_u32::<OUT>(7u32)?;
+
+            builder.write_u32::<OUT>(number_of_geometries)?;
+
+            for i in 0..number_of_geometries {
+                parse_geometry::<IN, OUT>(builder, cursor, bytes)?;
+            }
+        }
+        _ => {
+            return Err(DataFusionError::Execution(format!(
+                "Unsupported geometry type: {}",
+                wkb_type
+            )))
+        }
+    }
+
+    Ok(())
+}
+
+
+fn get_dimension(b: u8) -> Dimension {
+    match b {
+        1 => Dimension::XY,
+        2 => Dimension::XYZ,
+        3 => Dimension::XYM,
+        4 => Dimension::XYZM,
+        _ => Dimension::XY,
+    }
+}
diff --git a/rust/sedona-serde/src/lib.rs b/rust/sedona-serde/src/lib.rs
new file mode 100644
index 00000000..77397606
--- /dev/null
+++ b/rust/sedona-serde/src/lib.rs
@@ -0,0 +1,22 @@
+// 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.
+
+pub mod deserialize;
+mod point;
+mod linestring;
+mod polygon;
+mod wkb;
diff --git a/rust/sedona-serde/src/linestring.rs 
b/rust/sedona-serde/src/linestring.rs
new file mode 100644
index 00000000..1f7af45d
--- /dev/null
+++ b/rust/sedona-serde/src/linestring.rs
@@ -0,0 +1,98 @@
+// 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.
+
+use arrow_array::builder::BinaryBuilder;
+use byteorder::{ByteOrder, ReadBytesExt, WriteBytesExt};
+use std::io::{Cursor, Read, Write};
+use wkt::types::Dimension;
+use crate::wkb::write_wkb_byte_order_marker;
+
+fn get_linestring_marker(dimension: Dimension) -> u32 {
+    match dimension {
+        Dimension::XY => 2u32,
+        Dimension::XYZ => 1002u32,
+        Dimension::XYM => 2002u32,
+        Dimension::XYZM => 3002u32,
+    }
+}
+
+pub fn parse_linestring<IN: ByteOrder, OUT: ByteOrder>(
+    builder: &mut BinaryBuilder,
+    cursor: &mut Cursor<&[u8]>,
+    dimension: Dimension,
+) -> datafusion_common::Result<()> {
+    let number_of_points = cursor.read_u32::<IN>()?;
+    let byte_type = get_linestring_marker(dimension);
+
+    write_wkb_byte_order_marker(builder)?;
+
+    builder.write_u32::<OUT>(byte_type)?;
+
+    builder.write_u32::<OUT>(number_of_points)?;
+
+    let mut buf = [0u8; 8];
+    for _ in 0..number_of_points * 2 {
+        cursor.read_exact(&mut buf)?;
+        builder.write(&buf)?;
+    }
+
+    Ok(())
+}
+
+pub fn parse_multilinestring<IN: ByteOrder, OUT: ByteOrder>(
+    builder: &mut BinaryBuilder,
+    cursor: &mut Cursor<&[u8]>,
+    metadata_reader: &mut Cursor<&[u8]>,
+    dimension: Dimension,
+) -> datafusion_common::Result<()> {
+    let byte_type = match dimension {
+        Dimension::XY => 5u32,
+        Dimension::XYZ => 1005u32,
+        Dimension::XYM => 2005u32,
+        Dimension::XYZM => 3005u32,
+    };
+
+    let linestring_type = get_linestring_marker(dimension);
+
+    write_wkb_byte_order_marker(builder)?;
+    builder.write_u32::<OUT>(byte_type)?;
+
+    let number_of_points = cursor.read_u32::<IN>()?;
+
+    metadata_reader.set_position(cursor.position() + (number_of_points * 8 * 
2) as u64);
+
+    let number_of_geometries = metadata_reader.read_u32::<IN>()?;
+
+    builder.write_u32::<OUT>(number_of_geometries)?;
+
+    for _ in 0..number_of_geometries {
+        let number_of_points_in_linestring = metadata_reader.read_u32::<IN>()?;
+        write_wkb_byte_order_marker(builder)?;
+        builder.write_u32::<OUT>(linestring_type)?;
+
+        builder.write_u32::<OUT>(number_of_points_in_linestring)?;
+
+        for _ in 0..number_of_points_in_linestring * 2{
+            let mut buf = [0u8; 8];
+            cursor.read_exact(&mut buf)?;
+
+            builder.write(&buf)?;
+        }
+    }
+
+    Ok(())
+}
diff --git a/rust/sedona-serde/src/point.rs b/rust/sedona-serde/src/point.rs
new file mode 100644
index 00000000..5a6d7400
--- /dev/null
+++ b/rust/sedona-serde/src/point.rs
@@ -0,0 +1,96 @@
+// 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.
+
+use crate::wkb::write_wkb_byte_order_marker;
+use arrow_array::builder::BinaryBuilder;
+use byteorder::{ByteOrder, ReadBytesExt, WriteBytesExt};
+use datafusion_common::error::Result;
+use std::io::{Cursor, Read, Write};
+use wkt::types::Dimension;
+
+fn get_byte_type_for_point(dimension: Dimension) -> u32 {
+    match dimension {
+        Dimension::XY => 1u32,
+        Dimension::XYZ => 1001u32,
+        Dimension::XYM => 2001u32,
+        Dimension::XYZM => 3001u32,
+    }
+}
+
+pub fn write_empty_point<OUT: ByteOrder>(
+    builder: &mut BinaryBuilder,
+    dimension: Dimension,
+) -> Result<()> {
+    write_wkb_byte_order_marker(builder)?;
+    builder.write_u32::<OUT>(get_byte_type_for_point(dimension))?;
+
+    builder.write_f64::<OUT>(f64::NAN)?; // X
+    builder.write_f64::<OUT>(f64::NAN)?; // Y
+
+    Ok(())
+}
+
+pub fn parse_point<IN: ByteOrder, OUT: ByteOrder>(
+    builder: &mut BinaryBuilder,
+    cursor: &mut Cursor<&[u8]>,
+    dimension: Dimension,
+) -> Result<()> {
+    write_wkb_byte_order_marker(builder)?;
+    builder.write_u32::<OUT>(get_byte_type_for_point(dimension))?;
+
+    let mut buf = [0u8; 8];
+    cursor.read_exact(&mut buf)?;
+
+    builder.write(&buf)?;
+
+    cursor.read_exact(&mut buf)?;
+    builder.write(&buf)?;
+
+    Ok(())
+}
+
+pub fn parse_multipoint<IN: ByteOrder, OUT: ByteOrder>(
+    builder: &mut BinaryBuilder,
+    cursor: &mut Cursor<&[u8]>,
+    dimension: Dimension,
+) -> Result<()> {
+    let number_of_points = cursor.read_u32::<IN>()?;
+
+    let byte_type = match dimension {
+        Dimension::XY => 4u32,
+        Dimension::XYZ => 1004u32,
+        Dimension::XYM => 2004u32,
+        Dimension::XYZM => 3004u32,
+    };
+
+    write_wkb_byte_order_marker(builder)?;
+    builder.write_u32::<OUT>(byte_type)?;
+
+    if number_of_points == 0 {
+        builder.write_u32::<OUT>(0)?;
+        return Ok(());
+    }
+
+
+    builder.write_u32::<OUT>(number_of_points)?;
+
+    for _ in 0..number_of_points {
+        parse_point::<IN, OUT>(builder, cursor, dimension)?;
+    }
+
+    Ok(())
+}
diff --git a/rust/sedona-serde/src/polygon.rs b/rust/sedona-serde/src/polygon.rs
new file mode 100644
index 00000000..e46f1d22
--- /dev/null
+++ b/rust/sedona-serde/src/polygon.rs
@@ -0,0 +1,104 @@
+// 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.
+
+use std::io::{Cursor, Read, Write};
+use arrow_array::builder::BinaryBuilder;
+use byteorder::{ByteOrder, ReadBytesExt, WriteBytesExt};
+use wkt::types::Dimension;
+use crate::wkb::write_wkb_byte_order_marker;
+
+
+pub(crate) fn get_polygon_marker(dimension: Dimension) -> u32 {
+    match dimension {
+        Dimension::XY => 3u32,
+        Dimension::XYZ => 1003u32,
+        Dimension::XYM => 2003u32,
+        Dimension::XYZM => 3003u32,
+    }
+}
+
+pub fn parse_polygon<IN: ByteOrder, OUT: ByteOrder>(
+    builder: &mut BinaryBuilder,
+    cursor: &mut Cursor<&[u8]>,
+    metadata_reader: &mut Cursor<&[u8]>,
+    dimension: Dimension,
+) -> datafusion_common::Result<()> {
+    let byte_type = get_polygon_marker(dimension);
+    let number_of_rings = metadata_reader.read_u32::<IN>()?;
+
+    write_wkb_byte_order_marker(builder)?;
+    builder.write_u32::<OUT>(byte_type)?;
+    builder.write_u32::<OUT>(number_of_rings)?;
+
+    for _ in 0..number_of_rings {
+        let ring_number_of_points = metadata_reader.read_u32::<IN>()?;
+        builder.write_u32::<OUT>(ring_number_of_points)?;
+
+        let mut buf = [0u8; 8];
+        for _ in 0..ring_number_of_points * 2 {
+            cursor.read_exact(&mut buf)?;
+            builder.write(&buf)?;
+        }
+    }
+
+    Ok(())
+}
+
+pub(crate) fn parse_multipolygon<IN: ByteOrder, OUT: ByteOrder>(
+    builder: &mut BinaryBuilder,
+    cursor: &mut Cursor<&[u8]>,
+    metadata_reader: &mut Cursor<&[u8]>,
+    dimension: Dimension,
+) -> datafusion_common::Result<()> {
+    let byte_type = match dimension {
+        Dimension::XY => 6u32,
+        Dimension::XYZ => 1006u32,
+        Dimension::XYM => 2006u32,
+        Dimension::XYZM => 3006u32,
+    };
+
+    let number_of_points = cursor.read_u32::<IN>()?;
+    let metadata_start_position = number_of_points * 8 * 2;
+    metadata_reader.set_position(cursor.position() + (metadata_start_position) 
as u64);
+
+    let number_of_geometries = metadata_reader.read_u32::<IN>()?;
+    write_wkb_byte_order_marker(builder)?;
+    builder.write_u32::<OUT>(byte_type)?;
+    builder.write_u32::<OUT>(number_of_geometries)?;
+
+    for _ in 0..number_of_geometries {
+        parse_polygon::<IN, OUT>(builder, cursor, metadata_reader, dimension)?;
+    }
+
+    Ok(())
+}
+
+
+pub (crate) fn write_empty_polygon<OUT: ByteOrder>(builder: &mut 
BinaryBuilder, dimension: Dimension) -> datafusion_common::Result<()> {
+    let byte_type = match dimension {
+        Dimension::XY => 3u32,
+        Dimension::XYZ => 1003u32,
+        Dimension::XYM => 2003u32,
+        Dimension::XYZM => 3003u32,
+    };
+
+    write_wkb_byte_order_marker(builder)?;
+    builder.write_u32::<OUT>(byte_type)?;
+    builder.write_u32::<OUT>(0u32)?; // 0 rings
+    
+    Ok(())
+}
diff --git a/rust/sedona-serde/src/wkb.rs b/rust/sedona-serde/src/wkb.rs
new file mode 100644
index 00000000..d3b642ce
--- /dev/null
+++ b/rust/sedona-serde/src/wkb.rs
@@ -0,0 +1,24 @@
+// 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.
+
+use byteorder::WriteBytesExt;
+
+pub(crate) const WKB_LITTLE_ENDIAN_MARKER: u8 = 1;
+
+pub fn write_wkb_byte_order_marker<W: std::io::Write>(writer: &mut W) -> 
std::io::Result<()> {
+    writer.write_u8(WKB_LITTLE_ENDIAN_MARKER)
+}

Reply via email to