Crates.io | cobweb_asset_format |
lib.rs | cobweb_asset_format |
version | 0.2.1 |
created_at | 2025-05-16 04:28:36.001061+00 |
updated_at | 2025-07-05 20:18:57.261482+00 |
description | COB definition with parsing and ser/de. |
homepage | |
repository | https://github.com/UkoeHB/bevy_cobweb_ui |
max_upload_size | |
id | 1676068 |
size | 418,792 |
Attempt at a semi-formal specification for COB - WIP
Sub-crate of bevy_cobweb_ui
.
Comments, whitespace, and filler characters
// ... \n
\* ... *\
, \n
,
;
Banned characters outside string values and comments
non-basic ASCII whitespace: \b
, \f
, \r
, \t
any unicode character
manifest
self as {manifest key} {file} as {manifest key}
{id} {id}.{id}.{id}
import
{manifest key} as _ {manifest key} as {alias}
implicit: std as _ - can override, e.g. 'std as std'
{id}
defs
Definitions
Value constants
${name} = {value}
${name} = \ .. values .. \
Value macros
-
Loadable macros
Scene macros
Invocations
Value constants
${name}
${import::alias::path::to::}{name}
Value macros
-
Loadable macros
Scene macros
commands
Loadables
scenes
Scene layers
Loadables
Loadable macros
Scene macros
New layers
Loadable values appear in COB files very similar to how they appear in Rust. Since COB is minimalist, there are several simplifications and details to note.
Single-line and block comments are both supported, the same as rust.
// Single-line
/*
Multi-line
*/
Commas and semicolons are treated as whitespace. They are completely optional, even inside type generics.
Since we don't use commas to separate items, we have one important whitespace rule.
Important whitespace rule: All loadables and enum variants with data must have no whitespace between their name (or generics) and their data container ({}
, []
, or ()
).
Example (rust):
let s = MyStruct::<A, B<C, D>> { a: 10.0, b: true };
Example (COB):
MyStruct<A B<C D>>{ a: 10 b: true }
// No space here..^..
This rule lets us differentiate between a list of 'unit struct/variant, map/array/tuple' and a single 'struct/variant with data'.
Built-in keywords cannot be used as struct field names.
true
/false
: Boolean true/false.inf
/-inf
/nan
: Float values.none
: Corresponds to rust None
.auto
: Corresponds to enum variant Val::Auto
(used in UI, see built-in types below).Option<T>
If a rust type contains Option<T>
, then Some(T)
is elided to T
, and None
is represented by the none
keyword.
Example (rust):
#[derive(Reflect, Default, PartialEq)]
struct MyStruct
{
a: Option<u32>,
b: Option<bool>
}
let s = MyStruct{ a: Some(10), b: None };
Example (COB):
MyStruct{ a:10 b:none }
Type names inside loadable values are elided.
Example (rust):
#[derive(Reflect, Default, PartialEq)]
struct OtherStruct
{
a: u32
}
#[derive(Reflect, Default, PartialEq)]
enum OtherEnum
{
A,
B
}
#[derive(Reflect, Default, PartialEq)]
struct MyStruct
{
a: OtherStruct,
b: OtherEnum,
}
let s = MyStruct{ a: OtherStruct{ a: 10 }, b: OtherEnum::B };
Example (COB):
MyStruct{ a:{ a:10 } b:B }
Loadable type names are always required, since they are used to figure out how to deserialize values.
Example loadables (COB):
OtherStruct{ a:10 }
OtherEnum::A
When a newtype struct appears inside a loadable, the newtype is 'peeled' to the innermost non-newtype type.
Example (rust):
#[derive(Reflect, Default, PartialEq)]
struct MyNewtype(u32);
#[derive(Reflect, Default, PartialEq)]
struct MyStruct
{
a: MyNewtype(u32),
}
let s = MyStruct{ a: MyNewtype(10) };
Example (COB):
MyStruct{ a:10 }
// ^
// MyNewtype(10) simplified to 10
Instead of peeling, loadable newtypes and newtype enum variants use newtype collapsing. Newtypes are collapsed by discarding 'outer layers'.
Example (rust):
#[derive(Reflect, Default, PartialEq)]
struct MyStruct
{
a: u32,
}
#[derive(Reflect, Default, PartialEq)]
struct MyNewtype(MyStruct);
let s = MyNewtype(MyStruct{ a: 10 });
Example (COB):
MyNewtype{ a:10 }
// Un-collapsed: MyNewtype({ a:10 })
An important use-case for collapsing is bevy's Color
type.
Rust:
let c = Color::Srgba(Srgba{ red: 1.0, blue: 1.0, green: 1.0, alpha: 1.0 });
COB:
Srgba{ red:1 blue:1 green:1 alpha:1 }
Here we have Srgba
for the Color::Srgba
variant, and { ... }
for the Srgba{ ... }
inner struct's value.
Floats are written similar to how they are written in rust.
1.2e3
or 1.2E3
.1
can be written instead of 1.0
.inf
/-inf
/nan
: infinity, negative infinity, NaN
.Strings are handled similar to how rust string literals are handled.
"Hello, World!"
).\n
, \t
, \r
, \f
, \"
, \\
), in addition to Unicode code points (\u{..1-6 digit hex..}
).\
followed by a newline will be concatenated with the next non-space character on the next line.Since COB is part of bevy_cobweb_ui
, we include special support for two common UI types.
Val
: Val
variants can be written with special units (px
, %
, vw
, vh
, vmin
, vmax
, fr
) and the keyword auto
. For example, 10px
is equivalent to Px(10)
.
fr
variant corresponds to GridVal::Fraction
.Color
: The Color::Srgba
variant can be written with color-hex in the format #FFFFFF
(for alpha = 1.0
) or #AAFFFFFF
(for custom alpha
).Val::Px(1.0)
) will be converted to auto-builtin (e.g. 1.0px
)recover_fill