Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,26 @@ jobs:

- uses: actions-rust-lang/setup-rust-toolchain@v1

- name: Ensure Kotlin/Native Directory Exists
run: mkdir -p /home/runner/.kotlin-native
- name: Cache Kotlin/Native
id: cache-kotlin-native
uses: actions/cache@v4
with:
path: /home/runner/.kotlin-native
key: kotlin-native-v2.3.10-linux-x86_64
- name: Setup Additional Languages (kotlin/native)
if: ${{ steps.cache-kotlin-native.outputs.cache-hit != 'true' }}
run: |
KOTLIN_NATIVE_URL="https://github.com/JetBrains/kotlin/releases/download/v2.3.10/kotlin-native-prebuilt-linux-x86_64-2.3.10.tar.gz"
curl --fail --location --silent --show-error \
--retry 5 --retry-delay 2 --retry-all-errors \
--output /tmp/kotlin-native.tar.gz \
"${KOTLIN_NATIVE_URL}"
tar -xzf /tmp/kotlin-native.tar.gz -C /home/runner/.kotlin-native
- name: Add Kotlin/Native to PATH
run: echo "/home/runner/.kotlin-native/kotlin-native-prebuilt-linux-x86_64-2.3.10/bin" >> $GITHUB_PATH

- name: Setup Additional Languages (solidity)
uses: foundry-rs/foundry-toolchain@v1.2.0
- name: Ensure Solc Directory Exists
Expand Down Expand Up @@ -145,6 +165,7 @@ jobs:
deno --version
dart --version
swift --version
kotlinc-native -version
eval $(opam env)
ocaml --version

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ Currently, `serde-generate` generates type definitions and supports [Bincode](ht
* Swift
* OCaml
* Dart
* Kotlin
* Typescript (in progress)


Expand Down
7 changes: 6 additions & 1 deletion serde-generate-bin/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
//! '''

use serde_generate::{
cpp, csharp, dart, golang, java, ocaml, python3, rust, solidity, swift, typescript,
cpp, csharp, dart, golang, java, kotlin, ocaml, python3, rust, solidity, swift, typescript,
CodeGeneratorConfig, Encoding, SourceInstaller,
};
use serde_reflection::Registry;
Expand All @@ -30,6 +30,7 @@ enum Language {
CSharp,
Swift,
OCaml,
Kotlin,
}
}

Expand Down Expand Up @@ -180,6 +181,9 @@ fn main() {
Language::OCaml => ocaml::CodeGenerator::new(&config)
.output(&mut out, &registry)
.unwrap(),
Language::Kotlin => {
panic!("Code generation in Kotlin requires `--target-source-dir`")
}
}
}
}
Expand All @@ -202,6 +206,7 @@ fn main() {
Language::CSharp => Box::new(csharp::Installer::new(install_dir)),
Language::Swift => Box::new(swift::Installer::new(install_dir)),
Language::OCaml => Box::new(ocaml::Installer::new(install_dir)),
Language::Kotlin => Box::new(kotlin::Installer::new(install_dir)),
};

if let Some((registry, name)) = named_registry_opt {
Expand Down
3 changes: 2 additions & 1 deletion serde-generate/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,13 @@ revm = "19.2.0"
serde_json = "1.0.115"

[features]
default = ["cpp", "csharp", "dart", "golang", "java", "ocaml", "python3", "rust", "swift", "typescript", "solidity"]
default = ["cpp", "csharp", "dart", "golang", "java", "kotlin", "ocaml", "python3", "rust", "swift", "typescript", "solidity"]
cpp = []
csharp = ["include_dir"]
dart = ["include_dir"]
golang = []
java = ["include_dir"]
kotlin = ["include_dir"]
ocaml = ["phf", "include_dir"]
python3 = []
rust = []
Expand Down
59 changes: 59 additions & 0 deletions serde-generate/runtime/kotlin/com/novi/bcs/BcsDeserializer.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright (c) Zefchain Labs, Inc.
// SPDX-License-Identifier: MIT OR Apache-2.0

package com.novi.bcs

import com.novi.serde.BinaryDeserializer
import com.novi.serde.DeserializationError
import com.novi.serde.Slice

class BcsDeserializer(input: ByteArray) : BinaryDeserializer(input, BcsSerializer.MAX_CONTAINER_DEPTH) {
@Throws(DeserializationError::class)
override fun deserialize_f32(): Float {
throw DeserializationError("Not implemented: deserialize_f32")
}

@Throws(DeserializationError::class)
override fun deserialize_f64(): Double {
throw DeserializationError("Not implemented: deserialize_f64")
}

@Throws(DeserializationError::class)
private fun deserialize_uleb128_as_u32(): Int {
var value = 0L
var shift = 0
while (shift < 32) {
val x = getByte().toInt() and 0xff
val digit = x and 0x7f
value = value or (digit.toLong() shl shift)
if (value < 0 || value > Int.MAX_VALUE.toLong()) {
throw DeserializationError("Overflow while parsing uleb128-encoded uint32 value")
}
if (digit == x) {
if (shift > 0 && digit == 0) {
throw DeserializationError("Invalid uleb128 number (unexpected zero digit)")
}
return value.toInt()
}
shift += 7
}
throw DeserializationError("Overflow while parsing uleb128-encoded uint32 value")
}

@Throws(DeserializationError::class)
override fun deserialize_len(): Long {
return deserialize_uleb128_as_u32().toLong()
}

@Throws(DeserializationError::class)
override fun deserialize_variant_index(): Int {
return deserialize_uleb128_as_u32()
}

@Throws(DeserializationError::class)
override fun check_that_key_slices_are_increasing(key1: Slice, key2: Slice) {
if (Slice.compare_bytes(input, key1, key2) >= 0) {
throw DeserializationError("Error while decoding map: keys are not serialized in the expected order")
}
}
}
79 changes: 79 additions & 0 deletions serde-generate/runtime/kotlin/com/novi/bcs/BcsSerializer.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright (c) Zefchain Labs, Inc.
// SPDX-License-Identifier: MIT OR Apache-2.0

package com.novi.bcs

import com.novi.serde.BinarySerializer
import com.novi.serde.SerializationError
import com.novi.serde.Slice

class BcsSerializer : BinarySerializer(MAX_CONTAINER_DEPTH) {
@Throws(SerializationError::class)
override fun serialize_f32(value: Float) {
throw SerializationError("Not implemented: serialize_f32")
}

@Throws(SerializationError::class)
override fun serialize_f64(value: Double) {
throw SerializationError("Not implemented: serialize_f64")
}

private fun serialize_u32_as_uleb128(value: Int) {
var v = value
while ((v ushr 7) != 0) {
output.writeByte(((v and 0x7f) or 0x80).toByte())
v = v ushr 7
}
output.writeByte(v.toByte())
}

@Throws(SerializationError::class)
override fun serialize_len(value: Long) {
if (value < 0 || value > MAX_LENGTH) {
throw SerializationError("Incorrect length value")
}
serialize_u32_as_uleb128(value.toInt())
}

@Throws(SerializationError::class)
override fun serialize_variant_index(value: Int) {
serialize_u32_as_uleb128(value)
}

override fun sort_map_entries(offsets: IntArray) {
if (offsets.size <= 1) {
return
}
val offset0 = offsets[0]
val content = output.getBuffer()
val slices = Array(offsets.size) { index ->
if (index < offsets.size - 1) {
Slice(offsets[index], offsets[index + 1])
} else {
Slice(offsets[index], output.size())
}
}

slices.sortWith { slice1, slice2 ->
Slice.compare_bytes(content, slice1, slice2)
}

val totalLength = output.size() - offset0
val oldContent = ByteArray(totalLength)
content.copyInto(oldContent, startIndex = offset0, endIndex = offset0 + totalLength)

var position = offset0
for (slice in slices) {
val start = slice.start
val end = slice.end
val length = end - start
oldContent.copyInto(content, destinationOffset = position, startIndex = start - offset0, endIndex = start - offset0 + length)
position += length
}
}

companion object {
const val MAX_LENGTH: Long = Int.MAX_VALUE.toLong()
const val MAX_CONTAINER_DEPTH: Long = 500
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) Zefchain Labs, Inc.
// SPDX-License-Identifier: MIT OR Apache-2.0

package com.novi.bincode

import com.novi.serde.BinaryDeserializer
import com.novi.serde.DeserializationError
import com.novi.serde.Slice

class BincodeDeserializer(input: ByteArray) : BinaryDeserializer(input, Long.MAX_VALUE) {
@Throws(DeserializationError::class)
override fun deserialize_f32(): Float {
return Float.fromBits(getInt())
}

@Throws(DeserializationError::class)
override fun deserialize_f64(): Double {
return Double.fromBits(getLong())
}

@Throws(DeserializationError::class)
override fun deserialize_len(): Long {
val value = getLong()
if (value < 0 || value > Int.MAX_VALUE.toLong()) {
throw DeserializationError("Incorrect length value")
}
return value
}

@Throws(DeserializationError::class)
override fun deserialize_variant_index(): Int {
return getInt()
}

@Throws(DeserializationError::class)
override fun check_that_key_slices_are_increasing(key1: Slice, key2: Slice) {
// Not required by the format.
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright (c) Zefchain Labs, Inc.
// SPDX-License-Identifier: MIT OR Apache-2.0

package com.novi.bincode

import com.novi.serde.BinarySerializer
import com.novi.serde.SerializationError

class BincodeSerializer : BinarySerializer(Long.MAX_VALUE) {
@Throws(SerializationError::class)
override fun serialize_f32(value: Float) {
serialize_i32(value.toRawBits())
}

@Throws(SerializationError::class)
override fun serialize_f64(value: Double) {
serialize_i64(value.toRawBits())
}

@Throws(SerializationError::class)
override fun serialize_len(value: Long) {
serialize_u64(value.toULong())
}

@Throws(SerializationError::class)
override fun serialize_variant_index(value: Int) {
serialize_u32(value.toUInt())
}

override fun sort_map_entries(offsets: IntArray) {
// Not required by the format.
}
}
Loading
Loading