데이터 타입

← 메인 | English →


개요

Sigilaris datatype 모듈은 블록체인 기본 자료형을 위한 타입 안전한 불투명 타입(opaque type)을 제공하며, 내장 코덱 지원을 포함합니다. 이러한 타입들은 런타임 오버헤드 없이 컴파일 타임에 정확성을 보장합니다.

왜 특화된 데이터 타입이 필요한가?

블록체인 애플리케이션에서:

주요 특징

빠른 시작 (30초)

import org.sigilaris.core.datatype.*
import scodec.bits.ByteVector

// 256비트 부호 없는 정수
val hash = UInt256.fromHex("cafe").toOption.get
// hash: UInt256 = ByteVector(32 bytes, 0x000000000000000000000000000000000000000000000000000000000000cafe)

// 음이 아닌 임의 정밀도 정수
val amount = BigNat.unsafeFromLong(1000L)
// amount: BigNat = 1000

// 길이 접두사 UTF-8 문자열
val label = Utf8("account-1")
// label: Utf8 = "account-1"

이게 전부입니다! 이러한 타입들은 바이트 및 JSON 코덱과 원활하게 작동합니다.

데이터 타입

BigNat - 음이 아닌 임의 정밀도 정수

임의 정밀도를 가진 자연수(≥ 0):

import org.sigilaris.core.datatype.*

val n1 = BigNat.unsafeFromLong(42L)
// n1: BigNat = 42
val n2 = BigNat.unsafeFromLong(10L)
// n2: BigNat = 10

// 안전한 산술 연산
val sum = BigNat.add(n1, n2)  // 52
// sum: BigNat = 52
val product = BigNat.multiply(n1, n2)  // 420
// product: BigNat = 420

// 뺄셈은 Either를 반환
val diff = BigNat.tryToSubtract(n1, n2)  // Right(32)
// diff: Either[String, BigNat] = Right(value = 32)
val invalid = BigNat.tryToSubtract(n2, n1)  // Left("...")
// invalid: Either[String, BigNat] = Left(value = "Should be positive or zero")

주요 특징:

UInt256 - 256비트 부호 없는 정수

빅엔디안 표현의 고정 크기 256비트 부호 없는 정수:

import org.sigilaris.core.datatype.*
import scodec.bits.ByteVector

// 16진수 문자열로부터
val u1 = UInt256.fromHex("ff").toOption.get
// u1: UInt256 = ByteVector(32 bytes, 0x00000000000000000000000000000000000000000000000000000000000000ff)
val u2 = UInt256.fromHex("0x123abc").toOption.get
// u2: UInt256 = ByteVector(32 bytes, 0x0000000000000000000000000000000000000000000000000000000000123abc)

// BigInt로부터
val u3 = UInt256.fromBigIntUnsigned(BigInt(42)).toOption.get
// u3: UInt256 = ByteVector(32 bytes, 0x000000000000000000000000000000000000000000000000000000000000002a)

// 변환
val bigInt: BigInt = u1.toBigIntUnsigned
// bigInt: BigInt = 255
val hex: String = u1.toHexLower  // 소문자 16진수, 0x 접두사 없음
// hex: String = "00000000000000000000000000000000000000000000000000000000000000ff"

주요 특징:

Utf8 - 길이 접두사 UTF-8 문자열

길이 접두사 바이트 인코딩을 가진 UTF-8 문자열:

import org.sigilaris.core.datatype.*

val text = Utf8("Hello, 世界!")
// text: Utf8 = "Hello, 世界!"

// 문자열 변환
val str: String = text.asString
// str: String = "Hello, 世界!"

// Map 키로 사용 가능
val map = Map(Utf8("key1") -> 42, Utf8("key2") -> 100)
// map: Map[Utf8, Int] = Map("key1" -> 42, "key2" -> 100)

주요 특징:

코덱 통합

모든 타입은 내장 바이트 및 JSON 코덱을 가집니다:

import org.sigilaris.core.datatype.*
import org.sigilaris.core.codec.byte.{ByteEncoder, ByteDecoder}
import org.sigilaris.core.codec.json.{JsonEncoder, JsonDecoder}
import scodec.bits.ByteVector

val num = BigNat.unsafeFromLong(42L)
// num: BigNat = 42

// 바이트 인코딩
val bytes = ByteEncoder[BigNat].encode(num)
// bytes: ByteVector = Chunk(
//   bytes = View(
//     at = scodec.bits.ByteVector$AtArray@1016ffd,
//     offset = 0L,
//     size = 1L
//   )
// )
val decoded = ByteDecoder[BigNat].decode(bytes)
// decoded: Either[DecodeFailure, DecodeResult[BigNat]] = Right(
//   value = DecodeResult(
//     value = 42,
//     remainder = Chunk(
//       bytes = View(
//         at = scodec.bits.ByteVector$AtEmpty$@1e36eb43,
//         offset = 0L,
//         size = 0L
//       )
//     )
//   )
// )

// JSON 인코딩
val json = JsonEncoder[BigNat].encode(num)
// json: JsonValue = JString(value = "42")
val fromJson = JsonDecoder[BigNat].decode(json)
// fromJson: Either[DecodeFailure, BigNat] = Right(value = 42)

타입 안전성 예제

유효하지 않은 값 방지

import org.sigilaris.core.datatype.*
import scodec.bits.ByteVector

// BigNat: 음이 아닌 값의 컴파일 타임 보장
val valid = BigNat.fromBigInt(BigInt(100))  // Right(BigNat(100))
// valid: Either[String, BigNat] = Right(value = 100)
val invalid = BigNat.fromBigInt(BigInt(-1))  // Left("Constraint failed...")
// invalid: Either[String, BigNat] = Left(value = "Should be positive or zero")

// UInt256: 검증 오류에 대한 타입화된 실패
val overflow = UInt256.fromBigIntUnsigned(BigInt(2).pow(256))
// overflow: Either[UInt256Failure, UInt256] = Left(
//   value = UInt256Overflow(detail = "BigInt does not fit into 256 bits")
// )
// Left(UInt256Overflow("..."))

val tooLong = UInt256.fromBytesBE(ByteVector.fill(33)(0xff.toByte))
// tooLong: Either[UInt256Failure, UInt256] = Left(
//   value = UInt256TooLong(actualBytes = 33L, maxBytes = 32)
// )
// Left(UInt256TooLong(33, 32))

안전한 산술 연산

import org.sigilaris.core.datatype.*

val a = BigNat.unsafeFromLong(10L)
// a: BigNat = 10
val b = BigNat.unsafeFromLong(3L)
// b: BigNat = 3

// 항상 성공하는 연산
BigNat.add(a, b)       // 13
// res6: BigNat = 13
BigNat.multiply(a, b)  // 30
// res7: BigNat = 30
BigNat.divide(a, b)    // 3
// res8: BigNat = 3

// 실패할 수 있는 연산
BigNat.tryToSubtract(a, b)  // Right(7)
// res9: Either[String, BigNat] = Right(value = 7)
BigNat.tryToSubtract(b, a)  // Left("Constraint failed...")
// res10: Either[String, BigNat] = Left(value = "Should be positive or zero")

설계 철학

불투명 타입

검증된 생성

코덱 우선 설계

다음 단계

  1. BigNat: 임의 정밀도 자연수
  2. UInt256: 해시/주소를 위한 고정 크기 부호 없는 정수
  3. Utf8: 메타데이터를 위한 길이 접두사 문자열

← 메인 | English →