Skip to content

Commit 0a1c247

Browse files
authored
Merge pull request #20 from dimensionalOS/rust-codegen
Add Rust LCM code generator and generated bindings
2 parents 3c492d7 + e7c9428 commit 0a1c247

205 files changed

Lines changed: 19795 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ This will:
2121
4. Generate C# bindings (`generated/cs_lcm_msgs/`)
2222
5. Generate Java bindings (`generated/java_lcm_msgs/`)
2323
6. Generate Typescript bindings (`generated/ts_lcm_msgs/`)
24+
7. Generate Rust bindings (`generated/rust_lcm_msgs/`)
2425

2526
## Directory Structure
2627

generate.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,9 @@ deno run --allow-read --allow-write "$SCRIPT_DIR/tools/ts/gen/mod.ts" -q -o "$SC
4141
rm -rf "$SCRIPT_DIR/tools/ts/msgs/generated"
4242
cp -r "$SCRIPT_DIR/generated/ts_lcm_msgs" "$SCRIPT_DIR/tools/ts/msgs/generated"
4343
echo -e "\033[32mLCM -> TypeScript done\033[0m"
44+
45+
# Generate Rust bindings
46+
rm -rf "$SCRIPT_DIR/generated/rust_lcm_msgs"
47+
python3 "$SCRIPT_DIR/tools/rust/lcm_rust_gen.py" "$SCRIPT_DIR/lcm_types" -o "$SCRIPT_DIR/generated/rust_lcm_msgs"
48+
(cd "$SCRIPT_DIR/generated/rust_lcm_msgs" && cargo check --quiet)
49+
echo -e "\033[32mLCM -> Rust done\033[0m"

generated/rust_lcm_msgs/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/target

generated/rust_lcm_msgs/Cargo.lock

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

generated/rust_lcm_msgs/Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[package]
2+
name = "lcm-msgs"
3+
version = "0.1.0"
4+
edition = "2021"
5+
description = "Auto-generated LCM message types for Rust"
6+
7+
[dependencies]
8+
byteorder = "1"
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// Auto-generated by lcm-rust-gen. DO NOT EDIT.
2+
3+
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
4+
use std::io::{self, Read, Write, Cursor};
5+
use std::sync::OnceLock;
6+
7+
#[derive(Debug, Clone, Default, PartialEq)]
8+
pub struct GoalID {
9+
pub stamp: crate::std_msgs::Time,
10+
pub id: std::string::String,
11+
}
12+
13+
impl GoalID {
14+
pub const HASH: i64 = 0xEF36683EF0767E95u64 as i64;
15+
pub const NAME: &str = "actionlib_msgs.GoalID";
16+
17+
fn packed_fingerprint() -> u64 {
18+
static CACHE: OnceLock<u64> = OnceLock::new();
19+
*CACHE.get_or_init(|| Self::hash_recursive(&mut Vec::new()))
20+
}
21+
22+
pub(crate) fn hash_recursive(parents: &mut Vec<u64>) -> u64 {
23+
let self_hash = Self::HASH as u64;
24+
if parents.contains(&self_hash) {
25+
return 0;
26+
}
27+
parents.push(self_hash);
28+
let mut tmphash = self_hash as u64;
29+
tmphash = tmphash.wrapping_add(crate::std_msgs::Time::hash_recursive(parents));
30+
parents.pop();
31+
// rotate left by 1
32+
tmphash << 1 | tmphash >> 63
33+
}
34+
35+
pub fn encode(&self) -> Vec<u8> {
36+
let mut buf = Vec::with_capacity(8 + self.encoded_size());
37+
buf.write_u64::<BigEndian>(Self::packed_fingerprint()).unwrap();
38+
self.encode_one(&mut buf).unwrap();
39+
buf
40+
}
41+
42+
pub fn decode(data: &[u8]) -> io::Result<Self> {
43+
let mut cursor = Cursor::new(data);
44+
let hash = cursor.read_u64::<BigEndian>()?;
45+
let expected = Self::packed_fingerprint();
46+
if hash != expected {
47+
return Err(io::Error::new(io::ErrorKind::InvalidData,
48+
format!("Hash mismatch: expected {:016x}, got {:016x}", expected, hash)));
49+
}
50+
Self::decode_one(&mut cursor)
51+
}
52+
53+
pub fn encode_one<W: Write>(&self, buf: &mut W) -> io::Result<()> {
54+
self.stamp.encode_one(buf)?;
55+
{
56+
let bytes = self.id.as_bytes();
57+
buf.write_u32::<BigEndian>((bytes.len() + 1) as u32)?;
58+
buf.write_all(bytes)?;
59+
buf.write_u8(0)?;
60+
}
61+
Ok(())
62+
}
63+
64+
pub fn decode_one<R: Read>(buf: &mut R) -> io::Result<Self> {
65+
let stamp = crate::std_msgs::Time::decode_one(buf)?;
66+
let id = {
67+
let len = buf.read_u32::<BigEndian>()? as usize;
68+
let mut bytes = vec![0u8; len];
69+
buf.read_exact(&mut bytes)?;
70+
std::string::String::from_utf8(bytes[..len - 1].to_vec())
71+
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?
72+
};
73+
Ok(Self {
74+
stamp,
75+
id,
76+
})
77+
}
78+
79+
pub fn encoded_size(&self) -> usize {
80+
let mut size = 0usize;
81+
size += self.stamp.encoded_size();
82+
size += 4 + self.id.len() + 1;
83+
size
84+
}
85+
86+
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// Auto-generated by lcm-rust-gen. DO NOT EDIT.
2+
3+
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
4+
use std::io::{self, Read, Write, Cursor};
5+
use std::sync::OnceLock;
6+
7+
#[derive(Debug, Clone, Default, PartialEq)]
8+
pub struct GoalStatus {
9+
pub goal_id: crate::actionlib_msgs::GoalID,
10+
pub status: u8,
11+
pub text: std::string::String,
12+
}
13+
14+
impl GoalStatus {
15+
pub const HASH: i64 = 0xC0B4E95FEBDCD994u64 as i64;
16+
pub const NAME: &str = "actionlib_msgs.GoalStatus";
17+
18+
pub const PENDING: i8 = 0;
19+
pub const ACTIVE: i8 = 1;
20+
pub const PREEMPTED: i8 = 2;
21+
pub const SUCCEEDED: i8 = 3;
22+
pub const ABORTED: i8 = 4;
23+
pub const REJECTED: i8 = 5;
24+
pub const PREEMPTING: i8 = 6;
25+
pub const RECALLING: i8 = 7;
26+
pub const RECALLED: i8 = 8;
27+
pub const LOST: i8 = 9;
28+
29+
fn packed_fingerprint() -> u64 {
30+
static CACHE: OnceLock<u64> = OnceLock::new();
31+
*CACHE.get_or_init(|| Self::hash_recursive(&mut Vec::new()))
32+
}
33+
34+
pub(crate) fn hash_recursive(parents: &mut Vec<u64>) -> u64 {
35+
let self_hash = Self::HASH as u64;
36+
if parents.contains(&self_hash) {
37+
return 0;
38+
}
39+
parents.push(self_hash);
40+
let mut tmphash = self_hash as u64;
41+
tmphash = tmphash.wrapping_add(crate::actionlib_msgs::GoalID::hash_recursive(parents));
42+
parents.pop();
43+
// rotate left by 1
44+
tmphash << 1 | tmphash >> 63
45+
}
46+
47+
pub fn encode(&self) -> Vec<u8> {
48+
let mut buf = Vec::with_capacity(8 + self.encoded_size());
49+
buf.write_u64::<BigEndian>(Self::packed_fingerprint()).unwrap();
50+
self.encode_one(&mut buf).unwrap();
51+
buf
52+
}
53+
54+
pub fn decode(data: &[u8]) -> io::Result<Self> {
55+
let mut cursor = Cursor::new(data);
56+
let hash = cursor.read_u64::<BigEndian>()?;
57+
let expected = Self::packed_fingerprint();
58+
if hash != expected {
59+
return Err(io::Error::new(io::ErrorKind::InvalidData,
60+
format!("Hash mismatch: expected {:016x}, got {:016x}", expected, hash)));
61+
}
62+
Self::decode_one(&mut cursor)
63+
}
64+
65+
pub fn encode_one<W: Write>(&self, buf: &mut W) -> io::Result<()> {
66+
self.goal_id.encode_one(buf)?;
67+
buf.write_u8(self.status)?;
68+
{
69+
let bytes = self.text.as_bytes();
70+
buf.write_u32::<BigEndian>((bytes.len() + 1) as u32)?;
71+
buf.write_all(bytes)?;
72+
buf.write_u8(0)?;
73+
}
74+
Ok(())
75+
}
76+
77+
pub fn decode_one<R: Read>(buf: &mut R) -> io::Result<Self> {
78+
let goal_id = crate::actionlib_msgs::GoalID::decode_one(buf)?;
79+
let status = buf.read_u8()?;
80+
let text = {
81+
let len = buf.read_u32::<BigEndian>()? as usize;
82+
let mut bytes = vec![0u8; len];
83+
buf.read_exact(&mut bytes)?;
84+
std::string::String::from_utf8(bytes[..len - 1].to_vec())
85+
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?
86+
};
87+
Ok(Self {
88+
goal_id,
89+
status,
90+
text,
91+
})
92+
}
93+
94+
pub fn encoded_size(&self) -> usize {
95+
let mut size = 0usize;
96+
size += self.goal_id.encoded_size();
97+
size += 1;
98+
size += 4 + self.text.len() + 1;
99+
size
100+
}
101+
102+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
// Auto-generated by lcm-rust-gen. DO NOT EDIT.
2+
3+
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
4+
use std::io::{self, Read, Write, Cursor};
5+
use std::sync::OnceLock;
6+
7+
#[derive(Debug, Clone, Default, PartialEq)]
8+
pub struct GoalStatusArray {
9+
pub header: crate::std_msgs::Header,
10+
pub status_list: Vec<crate::actionlib_msgs::GoalStatus>,
11+
}
12+
13+
impl GoalStatusArray {
14+
pub const HASH: i64 = 0x0F5C35B2E7EED0FAu64 as i64;
15+
pub const NAME: &str = "actionlib_msgs.GoalStatusArray";
16+
17+
fn packed_fingerprint() -> u64 {
18+
static CACHE: OnceLock<u64> = OnceLock::new();
19+
*CACHE.get_or_init(|| Self::hash_recursive(&mut Vec::new()))
20+
}
21+
22+
pub(crate) fn hash_recursive(parents: &mut Vec<u64>) -> u64 {
23+
let self_hash = Self::HASH as u64;
24+
if parents.contains(&self_hash) {
25+
return 0;
26+
}
27+
parents.push(self_hash);
28+
let mut tmphash = self_hash as u64;
29+
tmphash = tmphash.wrapping_add(crate::std_msgs::Header::hash_recursive(parents));
30+
tmphash = tmphash.wrapping_add(crate::actionlib_msgs::GoalStatus::hash_recursive(parents));
31+
parents.pop();
32+
// rotate left by 1
33+
tmphash << 1 | tmphash >> 63
34+
}
35+
36+
pub fn encode(&self) -> Vec<u8> {
37+
let mut buf = Vec::with_capacity(8 + self.encoded_size());
38+
buf.write_u64::<BigEndian>(Self::packed_fingerprint()).unwrap();
39+
self.encode_one(&mut buf).unwrap();
40+
buf
41+
}
42+
43+
pub fn decode(data: &[u8]) -> io::Result<Self> {
44+
let mut cursor = Cursor::new(data);
45+
let hash = cursor.read_u64::<BigEndian>()?;
46+
let expected = Self::packed_fingerprint();
47+
if hash != expected {
48+
return Err(io::Error::new(io::ErrorKind::InvalidData,
49+
format!("Hash mismatch: expected {:016x}, got {:016x}", expected, hash)));
50+
}
51+
Self::decode_one(&mut cursor)
52+
}
53+
54+
pub fn encode_one<W: Write>(&self, buf: &mut W) -> io::Result<()> {
55+
buf.write_i32::<BigEndian>(self.status_list.len() as i32)?;
56+
self.header.encode_one(buf)?;
57+
for v0 in self.status_list.iter() {
58+
v0.encode_one(buf)?;
59+
}
60+
Ok(())
61+
}
62+
63+
pub fn decode_one<R: Read>(buf: &mut R) -> io::Result<Self> {
64+
let status_list_length = buf.read_i32::<BigEndian>()? as usize;
65+
let header = crate::std_msgs::Header::decode_one(buf)?;
66+
let status_list = {
67+
let mut v = Vec::with_capacity(status_list_length);
68+
for _ in 0..status_list_length {
69+
let _elem_0 = crate::actionlib_msgs::GoalStatus::decode_one(buf)?;
70+
v.push(_elem_0);
71+
}
72+
v
73+
};
74+
Ok(Self {
75+
header,
76+
status_list,
77+
})
78+
}
79+
80+
pub fn encoded_size(&self) -> usize {
81+
let mut size = 0usize;
82+
size += 4;
83+
size += self.header.encoded_size();
84+
for v0 in self.status_list.iter() {
85+
size += v0.encoded_size();
86+
}
87+
size
88+
}
89+
90+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Auto-generated by lcm-rust-gen. DO NOT EDIT.
2+
3+
mod goal_id;
4+
pub use goal_id::GoalID;
5+
6+
mod goal_status;
7+
pub use goal_status::GoalStatus;
8+
9+
mod goal_status_array;
10+
pub use goal_status_array::GoalStatusArray;

0 commit comments

Comments
 (0)