pub enum BrdbValue {
Show 20 variants
Nil,
Bool(bool),
U8(u8),
U16(u16),
U32(u32),
U64(u64),
I8(i8),
I16(i16),
I32(i32),
I64(i64),
F32(f32),
F64(f64),
String(String),
Asset(Option<usize>),
Enum(BrdbEnum),
Struct(Box<BrdbStruct>),
Array(Vec<BrdbValue>),
FlatArray(Vec<BrdbValue>),
Map(IndexMap<BrdbValue, BrdbValue>),
WireVar(WireVariant),
}Variants§
Nil
Bool(bool)
U8(u8)
U16(u16)
U32(u32)
U64(u64)
I8(i8)
I16(i16)
I32(i32)
I64(i64)
F32(f32)
F64(f64)
String(String)
Asset(Option<usize>)
Enum(BrdbEnum)
Struct(Box<BrdbStruct>)
Array(Vec<BrdbValue>)
FlatArray(Vec<BrdbValue>)
Map(IndexMap<BrdbValue, BrdbValue>)
WireVar(WireVariant)
Implementations§
Source§impl BrdbValue
impl BrdbValue
pub fn get_type(&self) -> &'static str
pub fn as_struct(&self) -> Result<&BrdbStruct, BrdbSchemaError>
pub fn prop(&self, prop: impl AsRef<str>) -> Result<&BrdbValue, BrdbSchemaError>
Sourcepub fn as_array(&self) -> Result<&Vec<BrdbValue>, BrdbSchemaError>
pub fn as_array(&self) -> Result<&Vec<BrdbValue>, BrdbSchemaError>
Examples found in repository?
examples/world_owner_tool.rs (line 47)
6fn main() -> Result<(), Box<dyn std::error::Error>> {
7 let mut args = std::env::args().into_iter().peekable();
8 let cmd = args.next().unwrap();
9 if !args.peek().is_some() {
10 println!("usage: {cmd} show world.brdb");
11 println!("usage: {cmd} apply world.brdb owners.csv");
12 println!(
13 "owners.csv must be `display_name,user_name,user_id,old_user_id` where old_user_id is the one to replace."
14 );
15 process::exit(0);
16 }
17
18 let command = args.next().unwrap();
19 if command != "show" && command != "apply" {
20 eprintln!("unknown command. expected `show` or `apply`");
21 process::exit(1);
22 }
23
24 let Some(file) = args.next() else {
25 eprintln!("missing world file arg");
26 process::exit(1);
27 };
28
29 let dst = PathBuf::from(&file);
30 if !dst.exists() {
31 eprintln!("file {file} does not exist");
32 process::exit(1);
33 }
34
35 let db = Brdb::open(dst)?.into_reader();
36
37 let owners = db.owners_soa()?;
38
39 if command == "show" {
40 if args.peek().is_some() {
41 eprintln!("too many arguments!");
42 process::exit(1);
43 }
44
45 let owners_csv = owners
46 .prop("DisplayNames")?
47 .as_array()?
48 .iter()
49 .zip(owners.prop("UserNames")?.as_array()?.iter())
50 .zip(owners.prop("UserIds")?.as_array()?.iter())
51 .map(|((display_name, user_name), user_id)| {
52 format!(
53 "{},{},{}",
54 display_name.as_str().unwrap(),
55 user_name.as_str().unwrap(),
56 Guid::try_from(user_id).unwrap().uuid(),
57 )
58 })
59 .collect::<Vec<_>>();
60 println!("display_name,user_name,user_id\n{}", owners_csv.join("\n"));
61 } else if command == "apply" {
62 let Some(apply_file) = args.next() else {
63 eprintln!("missing owners csv file arg");
64 process::exit(1);
65 };
66 if args.peek().is_some() {
67 eprintln!("too many arguments!");
68 process::exit(1);
69 }
70
71 let apply_path = PathBuf::from(&apply_file);
72 if !apply_path.exists() {
73 eprintln!("file {apply_file} does not exist");
74 process::exit(1);
75 }
76
77 let mut display_name_index = None;
78 let mut user_name_index = None;
79 let mut user_id_index = None;
80 let mut old_user_id_index = None;
81 let mut apply_data = String::new();
82 File::open(apply_path)?.read_to_string(&mut apply_data)?;
83 let Some((header, rows)) = apply_data.split_once("\n") else {
84 eprintln!("file {apply_file} does not have any rows");
85 process::exit(1);
86 };
87 for (i, key) in header.split(",").enumerate() {
88 match key.trim().to_ascii_lowercase().as_ref() {
89 "display_name" => {
90 display_name_index = Some(i);
91 }
92 "user_name" => {
93 user_name_index = Some(i);
94 }
95 "user_id" => {
96 user_id_index = Some(i);
97 }
98 "old_user_id" => old_user_id_index = Some(i),
99 other => {
100 eprintln!("unknown column {other} in {apply_file}");
101 process::exit(1);
102 }
103 }
104 }
105
106 let missing = [
107 ("display_name", display_name_index.is_none()),
108 ("user_name", user_name_index.is_none()),
109 ("user_id", user_id_index.is_none()),
110 ("old_user_id", old_user_id_index.is_none()),
111 ]
112 .into_iter()
113 .filter_map(|(k, cond)| cond.then_some(k.to_owned()))
114 .collect::<Vec<_>>();
115 if !missing.is_empty() {
116 eprintln!("missing columns: {}", missing.join(","));
117 process::exit(1);
118 }
119
120 let display_name_index = display_name_index.unwrap();
121 let user_name_index = user_name_index.unwrap();
122 let user_id_index = user_id_index.unwrap();
123 let old_user_id_index = old_user_id_index.unwrap();
124
125 // Parse the owners from BrdbValues
126 let mut new_soa = OwnerTableSoA::try_from(&owners.to_value())?;
127 let owners_lut = rows
128 .trim()
129 .split("\n")
130 .map(|r| r.trim().split(",").collect::<Vec<&str>>())
131 .map(|cols| {
132 let user_name = cols[user_name_index];
133 let display_name = cols[display_name_index];
134 let user_id = Uuid::parse_str(&cols[user_id_index])
135 .expect(&format!("invalid uuid: {}", cols[user_id_index]));
136 let old_user_id = Uuid::parse_str(&cols[old_user_id_index])
137 .expect(&format!("invalid old uuid: {}", cols[old_user_id_index]));
138 (old_user_id, (user_name, display_name, user_id))
139 })
140 .collect::<HashMap<_, _>>();
141 println!("{owners_lut:?}");
142
143 let mut changes = 0;
144
145 for i in 0..new_soa.user_ids.len() {
146 let old_id = new_soa.user_ids[i].uuid();
147 let Some((user_name, display_name, user_id)) = owners_lut.get(&old_id) else {
148 println!("missing old id for {old_id} - ignoring");
149 continue;
150 };
151 println!("replacing {old_id} with {user_id} - {user_name} ({display_name})");
152 new_soa.user_names[i] = (*user_name).to_owned();
153 new_soa.display_names[i] = (*display_name).to_owned();
154 new_soa.user_ids[i] = Guid::from_uuid((*user_id).clone());
155 changes += 1;
156 }
157
158 if changes == 0 {
159 println!("world left unchanged");
160 std::process::exit(0);
161 }
162
163 // convert the owners struct of arrays into bytes using the owners schema
164 let content = db.owners_schema()?.write_brdb(OWNER_TABLE_SOA, &new_soa)?;
165
166 let patch = BrPendingFs::Root(vec![(
167 "World".to_owned(),
168 BrPendingFs::Folder(Some(vec![(
169 "0".to_string(),
170 BrPendingFs::Folder(Some(vec![(
171 "Owners.mps".to_string(),
172 BrPendingFs::File(Some(content)),
173 )])),
174 )])),
175 )]);
176 db.write_pending("Replace owners", db.to_pending_patch()?.with_patch(patch)?)?;
177 println!("revision created")
178 }
179
180 Ok(())
181}pub fn index(&self, index: usize) -> Result<Option<&BrdbValue>, BrdbSchemaError>
pub fn index_unwrap(&self, index: usize) -> Result<&BrdbValue, BrdbSchemaError>
Sourcepub fn as_str(&self) -> Result<&str, BrdbSchemaError>
pub fn as_str(&self) -> Result<&str, BrdbSchemaError>
Examples found in repository?
examples/world_owner_tool.rs (line 54)
6fn main() -> Result<(), Box<dyn std::error::Error>> {
7 let mut args = std::env::args().into_iter().peekable();
8 let cmd = args.next().unwrap();
9 if !args.peek().is_some() {
10 println!("usage: {cmd} show world.brdb");
11 println!("usage: {cmd} apply world.brdb owners.csv");
12 println!(
13 "owners.csv must be `display_name,user_name,user_id,old_user_id` where old_user_id is the one to replace."
14 );
15 process::exit(0);
16 }
17
18 let command = args.next().unwrap();
19 if command != "show" && command != "apply" {
20 eprintln!("unknown command. expected `show` or `apply`");
21 process::exit(1);
22 }
23
24 let Some(file) = args.next() else {
25 eprintln!("missing world file arg");
26 process::exit(1);
27 };
28
29 let dst = PathBuf::from(&file);
30 if !dst.exists() {
31 eprintln!("file {file} does not exist");
32 process::exit(1);
33 }
34
35 let db = Brdb::open(dst)?.into_reader();
36
37 let owners = db.owners_soa()?;
38
39 if command == "show" {
40 if args.peek().is_some() {
41 eprintln!("too many arguments!");
42 process::exit(1);
43 }
44
45 let owners_csv = owners
46 .prop("DisplayNames")?
47 .as_array()?
48 .iter()
49 .zip(owners.prop("UserNames")?.as_array()?.iter())
50 .zip(owners.prop("UserIds")?.as_array()?.iter())
51 .map(|((display_name, user_name), user_id)| {
52 format!(
53 "{},{},{}",
54 display_name.as_str().unwrap(),
55 user_name.as_str().unwrap(),
56 Guid::try_from(user_id).unwrap().uuid(),
57 )
58 })
59 .collect::<Vec<_>>();
60 println!("display_name,user_name,user_id\n{}", owners_csv.join("\n"));
61 } else if command == "apply" {
62 let Some(apply_file) = args.next() else {
63 eprintln!("missing owners csv file arg");
64 process::exit(1);
65 };
66 if args.peek().is_some() {
67 eprintln!("too many arguments!");
68 process::exit(1);
69 }
70
71 let apply_path = PathBuf::from(&apply_file);
72 if !apply_path.exists() {
73 eprintln!("file {apply_file} does not exist");
74 process::exit(1);
75 }
76
77 let mut display_name_index = None;
78 let mut user_name_index = None;
79 let mut user_id_index = None;
80 let mut old_user_id_index = None;
81 let mut apply_data = String::new();
82 File::open(apply_path)?.read_to_string(&mut apply_data)?;
83 let Some((header, rows)) = apply_data.split_once("\n") else {
84 eprintln!("file {apply_file} does not have any rows");
85 process::exit(1);
86 };
87 for (i, key) in header.split(",").enumerate() {
88 match key.trim().to_ascii_lowercase().as_ref() {
89 "display_name" => {
90 display_name_index = Some(i);
91 }
92 "user_name" => {
93 user_name_index = Some(i);
94 }
95 "user_id" => {
96 user_id_index = Some(i);
97 }
98 "old_user_id" => old_user_id_index = Some(i),
99 other => {
100 eprintln!("unknown column {other} in {apply_file}");
101 process::exit(1);
102 }
103 }
104 }
105
106 let missing = [
107 ("display_name", display_name_index.is_none()),
108 ("user_name", user_name_index.is_none()),
109 ("user_id", user_id_index.is_none()),
110 ("old_user_id", old_user_id_index.is_none()),
111 ]
112 .into_iter()
113 .filter_map(|(k, cond)| cond.then_some(k.to_owned()))
114 .collect::<Vec<_>>();
115 if !missing.is_empty() {
116 eprintln!("missing columns: {}", missing.join(","));
117 process::exit(1);
118 }
119
120 let display_name_index = display_name_index.unwrap();
121 let user_name_index = user_name_index.unwrap();
122 let user_id_index = user_id_index.unwrap();
123 let old_user_id_index = old_user_id_index.unwrap();
124
125 // Parse the owners from BrdbValues
126 let mut new_soa = OwnerTableSoA::try_from(&owners.to_value())?;
127 let owners_lut = rows
128 .trim()
129 .split("\n")
130 .map(|r| r.trim().split(",").collect::<Vec<&str>>())
131 .map(|cols| {
132 let user_name = cols[user_name_index];
133 let display_name = cols[display_name_index];
134 let user_id = Uuid::parse_str(&cols[user_id_index])
135 .expect(&format!("invalid uuid: {}", cols[user_id_index]));
136 let old_user_id = Uuid::parse_str(&cols[old_user_id_index])
137 .expect(&format!("invalid old uuid: {}", cols[old_user_id_index]));
138 (old_user_id, (user_name, display_name, user_id))
139 })
140 .collect::<HashMap<_, _>>();
141 println!("{owners_lut:?}");
142
143 let mut changes = 0;
144
145 for i in 0..new_soa.user_ids.len() {
146 let old_id = new_soa.user_ids[i].uuid();
147 let Some((user_name, display_name, user_id)) = owners_lut.get(&old_id) else {
148 println!("missing old id for {old_id} - ignoring");
149 continue;
150 };
151 println!("replacing {old_id} with {user_id} - {user_name} ({display_name})");
152 new_soa.user_names[i] = (*user_name).to_owned();
153 new_soa.display_names[i] = (*display_name).to_owned();
154 new_soa.user_ids[i] = Guid::from_uuid((*user_id).clone());
155 changes += 1;
156 }
157
158 if changes == 0 {
159 println!("world left unchanged");
160 std::process::exit(0);
161 }
162
163 // convert the owners struct of arrays into bytes using the owners schema
164 let content = db.owners_schema()?.write_brdb(OWNER_TABLE_SOA, &new_soa)?;
165
166 let patch = BrPendingFs::Root(vec![(
167 "World".to_owned(),
168 BrPendingFs::Folder(Some(vec![(
169 "0".to_string(),
170 BrPendingFs::Folder(Some(vec![(
171 "Owners.mps".to_string(),
172 BrPendingFs::File(Some(content)),
173 )])),
174 )])),
175 )]);
176 db.write_pending("Replace owners", db.to_pending_patch()?.with_patch(patch)?)?;
177 println!("revision created")
178 }
179
180 Ok(())
181}pub fn display(&self, schema: &BrdbSchema) -> String
Trait Implementations§
Source§impl AsBrdbValue for BrdbValue
A default impl for BrdbValue.
impl AsBrdbValue for BrdbValue
A default impl for BrdbValue.
fn as_brdb_bool(&self) -> Result<bool, BrdbSchemaError>
fn as_brdb_u8(&self) -> Result<u8, BrdbSchemaError>
fn as_brdb_u16(&self) -> Result<u16, BrdbSchemaError>
fn as_brdb_u32(&self) -> Result<u32, BrdbSchemaError>
fn as_brdb_u64(&self) -> Result<u64, BrdbSchemaError>
fn as_brdb_i8(&self) -> Result<i8, BrdbSchemaError>
fn as_brdb_i16(&self) -> Result<i16, BrdbSchemaError>
fn as_brdb_i32(&self) -> Result<i32, BrdbSchemaError>
fn as_brdb_i64(&self) -> Result<i64, BrdbSchemaError>
fn as_brdb_f32(&self) -> Result<f32, BrdbSchemaError>
fn as_brdb_f64(&self) -> Result<f64, BrdbSchemaError>
fn as_brdb_str(&self) -> Result<&str, BrdbSchemaError>
fn as_brdb_asset( &self, _schema: &BrdbSchema, _ty: &str, ) -> Result<Option<usize>, BrdbSchemaError>
fn as_brdb_enum( &self, _schema: &BrdbSchema, _def: &BrdbSchemaEnum, ) -> Result<i32, BrdbSchemaError>
fn as_brdb_wire_variant(&self) -> Result<WireVariant, BrdbSchemaError>
Source§fn as_brdb_struct_prop_value(
&self,
schema: &BrdbSchema,
struct_name: BrdbInterned,
prop_name: BrdbInterned,
) -> Result<&dyn AsBrdbValue, BrdbSchemaError>
fn as_brdb_struct_prop_value( &self, schema: &BrdbSchema, struct_name: BrdbInterned, prop_name: BrdbInterned, ) -> Result<&dyn AsBrdbValue, BrdbSchemaError>
Read a specific struct property value from the schema.
Source§fn as_brdb_struct_prop_array(
&self,
schema: &BrdbSchema,
struct_name: BrdbInterned,
prop_name: BrdbInterned,
) -> Result<BrdbArrayIter<'_>, BrdbSchemaError>
fn as_brdb_struct_prop_array( &self, schema: &BrdbSchema, struct_name: BrdbInterned, prop_name: BrdbInterned, ) -> Result<BrdbArrayIter<'_>, BrdbSchemaError>
Get the the number of entries in a struct property.
Source§fn as_brdb_struct_prop_map(
&self,
schema: &BrdbSchema,
struct_name: BrdbInterned,
prop_name: BrdbInterned,
) -> Result<BrdbMapIter<'_>, BrdbSchemaError>
fn as_brdb_struct_prop_map( &self, schema: &BrdbSchema, struct_name: BrdbInterned, prop_name: BrdbInterned, ) -> Result<BrdbMapIter<'_>, BrdbSchemaError>
Get the the number of entries in a struct property.
Source§impl From<BrdbStruct> for BrdbValue
impl From<BrdbStruct> for BrdbValue
Source§fn from(value: BrdbStruct) -> Self
fn from(value: BrdbStruct) -> Self
Converts to this type from the input type.
Source§impl TryFrom<&BrdbValue> for BrickChunkSoA
impl TryFrom<&BrdbValue> for BrickChunkSoA
Source§impl TryFrom<&BrdbValue> for BrickSizeCounter
impl TryFrom<&BrdbValue> for BrickSizeCounter
Source§impl TryFrom<&BrdbValue> for ChunkIndex
impl TryFrom<&BrdbValue> for ChunkIndex
Source§impl TryFrom<&BrdbValue> for ComponentChunkSoA
impl TryFrom<&BrdbValue> for ComponentChunkSoA
Source§impl TryFrom<&BrdbValue> for ComponentTypeCounter
impl TryFrom<&BrdbValue> for ComponentTypeCounter
Source§impl TryFrom<&BrdbValue> for EntityChunkIndexSoA
impl TryFrom<&BrdbValue> for EntityChunkIndexSoA
Source§impl TryFrom<&BrdbValue> for EntityChunkSoA
impl TryFrom<&BrdbValue> for EntityChunkSoA
Source§impl TryFrom<&BrdbValue> for EntityColors
impl TryFrom<&BrdbValue> for EntityColors
Source§impl TryFrom<&BrdbValue> for EntityTypeCounter
impl TryFrom<&BrdbValue> for EntityTypeCounter
Source§impl TryFrom<&BrdbValue> for LocalWirePortSource
impl TryFrom<&BrdbValue> for LocalWirePortSource
Source§impl TryFrom<&BrdbValue> for OwnerTableSoA
impl TryFrom<&BrdbValue> for OwnerTableSoA
Source§impl TryFrom<&BrdbValue> for RelativePosition
impl TryFrom<&BrdbValue> for RelativePosition
Source§impl TryFrom<&BrdbValue> for RemoteWirePortSource
impl TryFrom<&BrdbValue> for RemoteWirePortSource
Source§impl TryFrom<&BrdbValue> for SavedBrickColor
impl TryFrom<&BrdbValue> for SavedBrickColor
Source§impl<'a, T: TryFrom<&'a BrdbValue, Error = BrdbSchemaError>> TryFrom<&'a BrdbValue> for Vec<T>
impl<'a, T: TryFrom<&'a BrdbValue, Error = BrdbSchemaError>> TryFrom<&'a BrdbValue> for Vec<T>
Source§impl TryFrom<&BrdbValue> for WireChunkSoA
impl TryFrom<&BrdbValue> for WireChunkSoA
Source§impl TryFrom<&BrdbValue> for WirePortTarget
impl TryFrom<&BrdbValue> for WirePortTarget
Source§impl TryFrom<BrdbValue> for BrickSizeCounter
impl TryFrom<BrdbValue> for BrickSizeCounter
Source§impl TryFrom<BrdbValue> for ChunkIndex
impl TryFrom<BrdbValue> for ChunkIndex
Source§impl TryFrom<BrdbValue> for SavedBrickColor
impl TryFrom<BrdbValue> for SavedBrickColor
impl Eq for BrdbValue
Auto Trait Implementations§
impl Freeze for BrdbValue
impl RefUnwindSafe for BrdbValue
impl Send for BrdbValue
impl Sync for BrdbValue
impl Unpin for BrdbValue
impl UnwindSafe for BrdbValue
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
Compare self to
key and return true if they are equal.Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
Converts
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
Converts
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more