#ethercat #fieldbus #beckhoff #automation #bit-field #ethercrab

无 std ethercrab-wire-derive

为 EtherCrab 提供推导宏

6 个版本

0.2.0 2024 年 7 月 28 日
0.1.4 2024 年 3 月 31 日
0.1.2 2024 年 2 月 3 日
0.1.1 2024 年 1 月 11 日

#6 in #位域

Download history 4/week @ 2024-04-22 5/week @ 2024-05-06 8/week @ 2024-05-13 23/week @ 2024-05-20 32/week @ 2024-05-27 52/week @ 2024-06-03 27/week @ 2024-06-10 43/week @ 2024-06-17 36/week @ 2024-06-24 45/week @ 2024-07-01 66/week @ 2024-07-08 77/week @ 2024-07-15 116/week @ 2024-07-22 189/week @ 2024-07-29 59/week @ 2024-08-05

每月 443 次下载
2 个包中使用(通过 ethercrab-wire

MIT/Apache

48KB
908 行代码(不含注释)

Build Status Crates.io Docs.rs

ethercrab-wire 提供推导属性。

实验性

这个包处于早期阶段,可能包含错误或随时发布破坏性更改。它在 ethercrab 中使用,并在那里得到良好的锻炼,但请在自己的代码中使用时谨慎。

这些推导支持具有位和(多)字节大小的字段的 struct,以及具有可选的 catch-all 变体的枚举。

支持的属性

Structs

  • #[wire(bits = N)] OR #[wire(bytes = N)]

    在网络上打包此 struct 的大小。这些属性可能不会同时存在。

Struct 字段

  • #[wire(bits = N)] OR #[wire(bytes = N)]

    此字段在网络上消耗的字节数。这些属性可能不会同时存在。

  • #[wire(pre_skip = N)]#[wire(pre_skip_bytes = N)]

    在打包表示中,在此字段之前或之后跳过一个或多个整个字节。

  • #[wire(post_skip = N)]#[wire(post_skip_bytes = N)]

    在原始数据中在此字段之后跳过多少位或字节。

    这些属性仅适用于宽度小于8位的字段。

枚举

枚举必须具有 #[repr()] 属性,并实现 Copy 特性。

枚举区分符

枚举区分符不得包含字段。

  • #[wire(备选方案= [])]

    具有此属性的区分符如果其直接值或列出的任何备选方案在输入数据中找到,则将被成功解析。

    区分符值在将数据打包到 wire 时使用。

  • #[wire(catch_all)]

    将此属性应用于具有单个未命名字段的区分符,该字段与枚举的 #[repr()] 相同的类型,以捕获任何未识别的值。

示例

具有位字段和多字节字段的 struct。

#[derive(ethercrab_wire::EtherCrabWireReadWrite)]
#[wire(bytes = 4)]
struct Mixed {
    #[wire(bits = 1)]
    one_bit: u8,
    #[wire(bits = 2)]
    two_bits: u8,

    // Fields that are 8 bits or larger must be byte aligned, so we skip the two remaining bits
    // of the previous byte with `post_skip`.
    #[wire(bits = 3, post_skip = 2)]
    three_bits: u8,

    /// Whole `u8`
    #[wire(bytes = 1)]
    one_byte: u8,

    /// Whole `u16`
    #[wire(bytes = 2)]
    one_word: u16,
}

具有 catch all 区分符和备选方案的枚举

#[derive(Copy, Clone, ethercrab_wire::EtherCrabWireReadWrite)]
#[repr(u8)]
enum OneByte {
    Foo = 0x01,
    #[wire(alternatives = [ 3, 4, 5, 6 ])]
    Bar = 0x02,
    Baz = 0x07,
    Quux = 0xab,
    #[wire(catch_all)]
    Unknown(u8),
}

// Normal discriminant
assert_eq!(OneByte::unpack_from_slice(&[0x07]), Ok(OneByte::Baz));

// Alternative value for `Bar`
assert_eq!(OneByte::unpack_from_slice(&[0x05]), Ok(OneByte::Bar));

// Catch all
assert_eq!(OneByte::unpack_from_slice(&[0xaa]), Ok(OneByte::Unknown(0xaa)));

Struct 字段对齐

1 字节或更多字节的 Struct 字段必须字节对齐。例如,以下 struct 将由于 bar 是 5 位“提前”而被拒绝

#[derive(ethercrab_wire::EtherCrabWireReadWrite)]
#[wire(bytes = 2)]
struct Broken {
    #[wire(bits = 3)]
    foo: u8,

    // There are 5 bits here unaccounted for

    #[wire(bytes = 1)]
    bar: u8,
}

可以通过使用 pre_skippost_skip 属性将下一个字段重新对齐到 8 位(或跳过整个输入数据的字节数)来轻松修复此问题

#[derive(ethercrab_wire::EtherCrabWireReadWrite)]
#[wire(bytes = 2)]
struct Fixed {
    #[wire(bits = 3, post_skip = 5)]
    foo: u8,
    #[wire(bytes = 1)]
    bar: u8,
}

字节中间的字段可以写成这样的形式,保持 8 位对齐

#[derive(ethercrab_wire::EtherCrabWireReadWrite)]
#[wire(bytes = 1)]
struct Middle {
    #[wire(pre_skip = 2, bits = 3, post_skip = 3)]
    foo: u8,
}

许可

在以下任一项下获得许可

任选之一。

依赖

~6–16MB
~189K SLoC