Created
February 22, 2024 02:17
-
-
Save brecert/ba53096765bfa3d1c788a9b0fc41a5dd to your computer and use it in GitHub Desktop.
ubjson.hexpat
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma author bree | |
#pragma description UBJSON ( Universal Binary JSON) format | |
#pragma MIME application/ubjson | |
#pragma endian big | |
#include <std/io.pat> | |
#include <std/mem.pat> | |
#include <std/string.pat> | |
namespace util { | |
fn warn(str fmt, auto ... args) { | |
str message = builtin::std::format(fmt, args); | |
str warn = std::format("$[{:#04x}] WARN: {}", $, message); | |
return std::print(warn); | |
}; | |
fn error(str fmt, auto ... args) { | |
str message = builtin::std::format(fmt, args); | |
str error = std::format("$[{:#04x}] ERROR: {}", $, message); | |
return std::error(error); | |
}; | |
fn debug(str fmt, auto ... args) { | |
str message = builtin::std::format(fmt, args); | |
str debug = std::format("$[{:#04x}] DEBUG: {}", $, message); | |
return std::print(debug); | |
}; | |
fn assert(bool condition, str fmt, auto ... args) { | |
if (!condition) { | |
str message = builtin::std::format(fmt, args); | |
str error = std::format("$[{:#04x}] ERROR(assert): {}", $, message); | |
return std::error(error); | |
} | |
}; | |
struct Lit<Type, auto ExpectedValue> { | |
Type value; | |
util::assert(value == ExpectedValue, "Expected \"{}\", got \"{}\"", ExpectedValue, value); | |
} [[sealed, format("util::impl::format_lit"), hidden]]; | |
struct DebugBytes<auto Size> { | |
if (DISPLAY_DEBUG_BYTES) { | |
u8 debug_bytes[Size] @ $ [[sealed, color("ffffff")]]; | |
} | |
}; | |
namespace impl { | |
fn format_lit(ref auto object) { | |
return object.value; | |
}; | |
} | |
} | |
fn read_u8() { | |
return std::mem::read_unsigned($, 1, std::mem::Endian::Big); | |
}; | |
// START | |
using IntNum; | |
using Array; | |
using Object; | |
using String; | |
using HighPrecisionNumber; | |
enum Marker : u8 { | |
Null = 'Z', | |
NoOp = 'N', | |
True = 'T', | |
False = 'F', | |
Int8 = 'i', | |
UInt8 = 'U', | |
Int16 = 'I', | |
Int32 = 'l', | |
Int64 = 'L', | |
Float32 = 'd', | |
Float64 = 'D', | |
HighPrecisionNumber = 'H', | |
Char = 'C', | |
String = 'S', | |
Array = '[', | |
ArrayEnd = ']', | |
Object = '{', | |
ObjectEnd = '}', | |
}; | |
struct Value { | |
Marker type; | |
match (type) { | |
(Marker::Int8): s8 value; | |
(Marker::UInt8): u8 value; | |
(Marker::Int16): s16 value; | |
(Marker::Int32): s32 value; | |
(Marker::Int64): s64 value; | |
(Marker::Float32): float value; | |
(Marker::Float64): double value; | |
(Marker::HighPrecisionNumber): HighPrecisionNumber value; | |
(Marker::Char): char value; | |
(Marker::String): String value; | |
(Marker::Array): Array value; | |
(Marker::Object): Object value; | |
} | |
} [[transform("transform_value"), inline]]; | |
fn transform_value(ref auto object) { | |
return object.value; | |
}; | |
fn transform_values(ref auto object) { | |
return object.values; | |
}; | |
struct TypedPair<Type> { | |
String name; | |
Type value; | |
}; | |
struct Pair { | |
String name; | |
Value value; | |
}; | |
struct Array { | |
match (read_u8()) { | |
('#'): { | |
util::Lit<u8, '#'>; | |
IntNum count; | |
Value values[count]; | |
} | |
('$'): { | |
util::Lit<u8, '$'>; | |
Marker type; | |
util::Lit<u8, '#'>; | |
IntNum count; | |
match (type) { | |
(Marker::Int8): s8 values[count.num]; | |
(Marker::UInt8): u8 values[count.num]; | |
(Marker::Int16): s16 values[count.num]; | |
(Marker::Int32): s32 values[count.num]; | |
(Marker::Int64): s64 values[count.num]; | |
(Marker::Float32): float values[count.num]; | |
(Marker::Float64): double values[count.num]; | |
(Marker::HighPrecisionNumber): HighPrecisionNumber values[count.num]; | |
(Marker::Char): char values[count.num]; | |
(Marker::String): String values[count.num]; | |
(Marker::Array): Array values[count.num]; | |
(Marker::Object): Object values[count.num]; | |
} | |
} | |
(_): { | |
Value values[while(read_u8() != Marker::ArrayEnd)]; | |
util::Lit<u8, Marker::ArrayEnd>; | |
} | |
} | |
} [[transform("transform_values")]]; | |
struct Object { | |
match (read_u8()) { | |
('#'): { | |
util::Lit<u8, '#'>; | |
IntNum count; | |
Pair values[count]; | |
} | |
('$'): { | |
util::Lit<u8, '$'>; | |
Marker type; | |
util::Lit<u8, '#'>; | |
IntNum count; | |
match (TypeMarker) { | |
(Marker::Int8): TypedPair<s8> values[count.num]; | |
(Marker::UInt8): TypedPair<u8> values[count.num]; | |
(Marker::Int16): TypedPair<s16> values[count.num]; | |
(Marker::Int32): TypedPair<s32> values[count.num]; | |
(Marker::Int64): TypedPair<s64> values[count.num]; | |
(Marker::Float32): TypedPair<float> values[count.num]; | |
(Marker::Float64): TypedPair<double> values[count.num]; | |
(Marker::HighPrecisionNumber): TypedPair<HighPrecisionNumber> values[count.num]; | |
(Marker::Char): TypedPair<char> values[count.num]; | |
(Marker::String): TypedPair<String> values[count.num]; | |
(Marker::Array): TypedPair<Array> values[count.num]; | |
(Marker::Object): TypedPair<Object> values[count.num]; | |
} | |
} | |
(_): { | |
Pair values[while(read_u8() != Marker::ObjectEnd)]; | |
util::Lit<u8, Marker::ObjectEnd>; | |
} | |
} | |
} [[transform("transform_values"), inline]]; | |
struct IntNum { | |
Value value [[inline]]; | |
match (value.type) { | |
(Marker::Int8 | Marker::UInt8 | Marker::Int16 | Marker::Int32 | Marker::Int64): {} | |
(_): util::error("int num must be of type uint8, int8, int16, int32, or int64. not {}", value.type); | |
} | |
u128 num = value.value [[export]]; | |
} [[sealed, transform("transform_value"), format("transform_value")]]; | |
struct String { | |
IntNum size; | |
char data[size.num]; | |
} [[sealed, format("format_string")]]; | |
fn format_string(auto string) { | |
return string.data; | |
}; | |
struct HighPrecisionNumber { | |
String value; | |
}; | |
Value document @ 0x00; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment