From 5f39afeb4e8fa39bd6813b7d2c65d34d82eeaf8d Mon Sep 17 00:00:00 2001 From: Woshiluo Luo Date: Tue, 29 Oct 2024 20:58:30 +0800 Subject: [PATCH 01/10] fix: write StructDeserializer.cursor Signed-off-by: Woshiluo Luo --- src/de_mut/node.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/de_mut/node.rs b/src/de_mut/node.rs index 2e7167b..d9e1eca 100644 --- a/src/de_mut/node.rs +++ b/src/de_mut/node.rs @@ -51,7 +51,7 @@ impl<'de> Node<'de> { unsafe fn covnert_from_struct_deseriallizer_pointer( ptr: *const &StructDeserializer<'de>, ) -> Self { - let struct_deseriallizer = &*(ptr); + let struct_deseriallizer = &mut *(ptr as *mut &mut StructDeserializer<'de>); let dtb = struct_deseriallizer.dtb; let mut cursor = struct_deseriallizer.cursor; let mut prop: Option = None; @@ -81,6 +81,7 @@ impl<'de> Node<'de> { } } } + struct_deseriallizer.cursor = cursor; Node { cursor: struct_deseriallizer.cursor, reg: struct_deseriallizer.reg, @@ -90,6 +91,7 @@ impl<'de> Node<'de> { } } + // TODO: Maybe use BTreeMap when have alloc /// 获得节点迭代器。 pub const fn nodes<'b>(&'b self) -> Option> { match self.nodes_start { From 2865dd181c877f32cf4ae5844c373bbb6bce0756 Mon Sep 17 00:00:00 2001 From: Woshiluo Luo Date: Tue, 29 Oct 2024 21:24:01 +0800 Subject: [PATCH 02/10] feat: add utils for search fdt and find a node in fdt Signed-off-by: Woshiluo Luo --- examples/hifive-unmatched-a00.dts | 655 ++++++++++++++++++++++++++++++ src/lib.rs | 1 + src/utils/mod.rs | 121 ++++++ 3 files changed, 777 insertions(+) create mode 100644 examples/hifive-unmatched-a00.dts create mode 100644 src/utils/mod.rs diff --git a/examples/hifive-unmatched-a00.dts b/examples/hifive-unmatched-a00.dts new file mode 100644 index 0000000..e127454 --- /dev/null +++ b/examples/hifive-unmatched-a00.dts @@ -0,0 +1,655 @@ +/dts-v1/; + +/ { + #address-cells = <0x02>; + #size-cells = <0x02>; + compatible = "sifive,hifive-unmatched-a00", "sifive,fu740-c000", "sifive,fu740"; + model = "SiFive HiFive Unmatched A00"; + + aliases { + serial0 = "/soc/serial@10010000"; + serial1 = "/soc/serial@10011000"; + ethernet0 = "/soc/ethernet@10090000"; + spi0 = "/soc/spi@10050000"; + }; + + chosen { + stdout-path = "serial0"; + }; + + cpus { + #address-cells = <0x01>; + #size-cells = <0x00>; + timebase-frequency = <0xf4240>; + assigned-clocks = <0x01 0x00>; + assigned-clock-rates = <0x47868c00>; + u-boot,dm-spl; + + cpu@0 { + compatible = "sifive,bullet0", "riscv"; + device_type = "cpu"; + i-cache-block-size = <0x40>; + i-cache-sets = <0x80>; + i-cache-size = <0x4000>; + next-level-cache = <0x02>; + reg = <0x00>; + riscv,isa = "rv64imac"; + status = "okay"; + clocks = <0x01 0x00>; + u-boot,dm-spl; + + interrupt-controller { + #interrupt-cells = <0x01>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + u-boot,dm-spl; + phandle = <0x03>; + }; + }; + + cpu@1 { + compatible = "sifive,bullet0", "riscv"; + d-cache-block-size = <0x40>; + d-cache-sets = <0x40>; + d-cache-size = <0x8000>; + d-tlb-sets = <0x01>; + d-tlb-size = <0x28>; + device_type = "cpu"; + i-cache-block-size = <0x40>; + i-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-tlb-sets = <0x01>; + i-tlb-size = <0x28>; + mmu-type = "riscv,sv39"; + next-level-cache = <0x02>; + reg = <0x01>; + riscv,isa = "rv64imafdc"; + tlb-split; + clocks = <0x01 0x00>; + u-boot,dm-spl; + + interrupt-controller { + #interrupt-cells = <0x01>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + u-boot,dm-spl; + phandle = <0x04>; + }; + }; + + cpu@2 { + compatible = "sifive,bullet0", "riscv"; + d-cache-block-size = <0x40>; + d-cache-sets = <0x40>; + d-cache-size = <0x8000>; + d-tlb-sets = <0x01>; + d-tlb-size = <0x28>; + device_type = "cpu"; + i-cache-block-size = <0x40>; + i-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-tlb-sets = <0x01>; + i-tlb-size = <0x28>; + mmu-type = "riscv,sv39"; + next-level-cache = <0x02>; + reg = <0x02>; + riscv,isa = "rv64imafdc"; + tlb-split; + clocks = <0x01 0x00>; + u-boot,dm-spl; + + interrupt-controller { + #interrupt-cells = <0x01>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + u-boot,dm-spl; + phandle = <0x05>; + }; + }; + + cpu@3 { + compatible = "sifive,bullet0", "riscv"; + d-cache-block-size = <0x40>; + d-cache-sets = <0x40>; + d-cache-size = <0x8000>; + d-tlb-sets = <0x01>; + d-tlb-size = <0x28>; + device_type = "cpu"; + i-cache-block-size = <0x40>; + i-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-tlb-sets = <0x01>; + i-tlb-size = <0x28>; + mmu-type = "riscv,sv39"; + next-level-cache = <0x02>; + reg = <0x03>; + riscv,isa = "rv64imafdc"; + tlb-split; + clocks = <0x01 0x00>; + u-boot,dm-spl; + + interrupt-controller { + #interrupt-cells = <0x01>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + u-boot,dm-spl; + phandle = <0x06>; + }; + }; + + cpu@4 { + compatible = "sifive,bullet0", "riscv"; + d-cache-block-size = <0x40>; + d-cache-sets = <0x40>; + d-cache-size = <0x8000>; + d-tlb-sets = <0x01>; + d-tlb-size = <0x28>; + device_type = "cpu"; + i-cache-block-size = <0x40>; + i-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-tlb-sets = <0x01>; + i-tlb-size = <0x28>; + mmu-type = "riscv,sv39"; + next-level-cache = <0x02>; + reg = <0x04>; + riscv,isa = "rv64imafdc"; + tlb-split; + clocks = <0x01 0x00>; + u-boot,dm-spl; + + interrupt-controller { + #interrupt-cells = <0x01>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + u-boot,dm-spl; + phandle = <0x07>; + }; + }; + }; + + soc { + #address-cells = <0x02>; + #size-cells = <0x02>; + compatible = "sifive,fu740-c000", "sifive,fu740", "simple-bus"; + ranges; + u-boot,dm-spl; + + interrupt-controller@c000000 { + #interrupt-cells = <0x01>; + compatible = "sifive,plic-1.0.0"; + reg = <0x00 0xc000000 0x00 0x4000000>; + riscv,ndev = <0x45>; + interrupt-controller; + interrupts-extended = <0x03 0xffffffff 0x04 0xffffffff 0x04 0x09 0x05 0xffffffff 0x05 0x09 0x06 0xffffffff 0x06 0x09 0x07 0xffffffff 0x07 0x09>; + phandle = <0x0a>; + }; + + clock-controller@10000000 { + compatible = "sifive,fu740-c000-prci"; + reg = <0x00 0x10000000 0x00 0x1000>; + clocks = <0x08 0x09>; + #clock-cells = <0x01>; + #reset-cells = <0x01>; + resets = <0x01 0x00 0x01 0x01 0x01 0x02 0x01 0x03 0x01 0x05 0x01 0x06>; + reset-names = "ddr_ctrl", "ddr_axi", "ddr_ahb", "ddr_phy", "gemgxl_reset", "cltx_reset"; + u-boot,dm-spl; + phandle = <0x01>; + }; + + serial@10010000 { + compatible = "sifive,fu740-c000-uart", "sifive,uart0"; + reg = <0x00 0x10010000 0x00 0x1000>; + interrupt-parent = <0x0a>; + interrupts = <0x27>; + clocks = <0x01 0x07>; + status = "okay"; + u-boot,dm-spl; + }; + + serial@10011000 { + compatible = "sifive,fu740-c000-uart", "sifive,uart0"; + reg = <0x00 0x10011000 0x00 0x1000>; + interrupt-parent = <0x0a>; + interrupts = <0x28>; + clocks = <0x01 0x07>; + status = "okay"; + }; + + i2c@10030000 { + compatible = "sifive,fu740-c000-i2c", "sifive,i2c0"; + reg = <0x00 0x10030000 0x00 0x1000>; + interrupt-parent = <0x0a>; + interrupts = <0x34>; + clocks = <0x01 0x07>; + reg-shift = <0x02>; + reg-io-width = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "okay"; + u-boot,dm-spl; + + temperature-sensor@4c { + compatible = "ti,tmp451"; + reg = <0x4c>; + interrupt-parent = <0x0b>; + interrupts = <0x06 0x08>; + }; + + pmic@58 { + compatible = "dlg,da9063"; + reg = <0x58>; + interrupt-parent = <0x0b>; + interrupts = <0x01 0x08>; + interrupt-controller; + + regulators { + + bcore1 { + regulator-min-microvolt = <0x100590>; + regulator-max-microvolt = <0x100590>; + regulator-min-microamp = <0x4c4b40>; + regulator-max-microamp = <0x4c4b40>; + regulator-always-on; + }; + + bcore2 { + regulator-min-microvolt = <0x100590>; + regulator-max-microvolt = <0x100590>; + regulator-min-microamp = <0x4c4b40>; + regulator-max-microamp = <0x4c4b40>; + regulator-always-on; + }; + + bpro { + regulator-min-microvolt = <0x1b7740>; + regulator-max-microvolt = <0x1b7740>; + regulator-min-microamp = <0x2625a0>; + regulator-max-microamp = <0x2625a0>; + regulator-always-on; + }; + + bperi { + regulator-min-microvolt = <0x100590>; + regulator-max-microvolt = <0x100590>; + regulator-min-microamp = <0x16e360>; + regulator-max-microamp = <0x16e360>; + regulator-always-on; + }; + + bmem { + regulator-min-microvolt = <0x124f80>; + regulator-max-microvolt = <0x124f80>; + regulator-min-microamp = <0x2dc6c0>; + regulator-max-microamp = <0x2dc6c0>; + regulator-always-on; + }; + + bio { + regulator-min-microvolt = <0x124f80>; + regulator-max-microvolt = <0x124f80>; + regulator-min-microamp = <0x2dc6c0>; + regulator-max-microamp = <0x2dc6c0>; + regulator-always-on; + }; + + ldo1 { + regulator-min-microvolt = <0x1b7740>; + regulator-max-microvolt = <0x1b7740>; + regulator-min-microamp = <0x186a0>; + regulator-max-microamp = <0x186a0>; + regulator-always-on; + }; + + ldo2 { + regulator-min-microvolt = <0x1b7740>; + regulator-max-microvolt = <0x1b7740>; + regulator-min-microamp = <0x30d40>; + regulator-max-microamp = <0x30d40>; + regulator-always-on; + }; + + ldo3 { + regulator-min-microvolt = <0x325aa0>; + regulator-max-microvolt = <0x325aa0>; + regulator-min-microamp = <0x30d40>; + regulator-max-microamp = <0x30d40>; + regulator-always-on; + }; + + ldo4 { + regulator-min-microvolt = <0x2625a0>; + regulator-max-microvolt = <0x2625a0>; + regulator-min-microamp = <0x30d40>; + regulator-max-microamp = <0x30d40>; + regulator-always-on; + }; + + ldo5 { + regulator-min-microvolt = <0x325aa0>; + regulator-max-microvolt = <0x325aa0>; + regulator-min-microamp = <0x186a0>; + regulator-max-microamp = <0x186a0>; + regulator-always-on; + }; + + ldo6 { + regulator-min-microvolt = <0x1b7740>; + regulator-max-microvolt = <0x1b7740>; + regulator-min-microamp = <0x30d40>; + regulator-max-microamp = <0x30d40>; + regulator-always-on; + }; + + ldo7 { + regulator-min-microvolt = <0x325aa0>; + regulator-max-microvolt = <0x325aa0>; + regulator-min-microamp = <0x30d40>; + regulator-max-microamp = <0x30d40>; + regulator-always-on; + }; + + ldo8 { + regulator-min-microvolt = <0x325aa0>; + regulator-max-microvolt = <0x325aa0>; + regulator-min-microamp = <0x30d40>; + regulator-max-microamp = <0x30d40>; + regulator-always-on; + }; + + ldo9 { + regulator-min-microvolt = <0x100590>; + regulator-max-microvolt = <0x100590>; + regulator-min-microamp = <0x30d40>; + regulator-max-microamp = <0x30d40>; + }; + + ldo10 { + regulator-min-microvolt = <0xf4240>; + regulator-max-microvolt = <0xf4240>; + regulator-min-microamp = <0x493e0>; + regulator-max-microamp = <0x493e0>; + }; + + ldo11 { + regulator-min-microvolt = <0x2625a0>; + regulator-max-microvolt = <0x2625a0>; + regulator-min-microamp = <0x493e0>; + regulator-max-microamp = <0x493e0>; + regulator-always-on; + }; + }; + }; + }; + + i2c@10031000 { + compatible = "sifive,fu740-c000-i2c", "sifive,i2c0"; + reg = <0x00 0x10031000 0x00 0x1000>; + interrupt-parent = <0x0a>; + interrupts = <0x35>; + clocks = <0x01 0x07>; + reg-shift = <0x02>; + reg-io-width = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + }; + + spi@10040000 { + compatible = "sifive,fu740-c000-spi", "sifive,spi0"; + reg = <0x00 0x10040000 0x00 0x1000 0x00 0x20000000 0x00 0x10000000>; + interrupt-parent = <0x0a>; + interrupts = <0x29>; + clocks = <0x01 0x07>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "okay"; + + flash@0 { + compatible = "issi,is25wp256", "jedec,spi-nor"; + reg = <0x00>; + spi-max-frequency = <0x2faf080>; + m25p,fast-read; + spi-tx-bus-width = <0x04>; + spi-rx-bus-width = <0x04>; + }; + }; + + spi@10041000 { + compatible = "sifive,fu740-c000-spi", "sifive,spi0"; + reg = <0x00 0x10041000 0x00 0x1000 0x00 0x30000000 0x00 0x10000000>; + interrupt-parent = <0x0a>; + interrupts = <0x2a>; + clocks = <0x01 0x07>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + }; + + spi@10050000 { + compatible = "sifive,fu740-c000-spi", "sifive,spi0"; + reg = <0x00 0x10050000 0x00 0x1000>; + interrupt-parent = <0x0a>; + interrupts = <0x2b>; + clocks = <0x01 0x07>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "okay"; + u-boot,dm-spl; + + mmc@0 { + compatible = "mmc-spi-slot"; + reg = <0x00>; + spi-max-frequency = <0x1312d00>; + voltage-ranges = <0xce4 0xce4>; + disable-wp; + u-boot,dm-spl; + }; + }; + + ethernet@10090000 { + compatible = "sifive,fu540-c000-gem"; + interrupt-parent = <0x0a>; + interrupts = <0x37>; + reg = <0x00 0x10090000 0x00 0x2000 0x00 0x100a0000 0x00 0x1000>; + local-mac-address = [00 00 00 00 00 00]; + clock-names = "pclk", "hclk"; + clocks = <0x01 0x02 0x01 0x02>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "okay"; + phy-mode = "gmii"; + phy-handle = <0x0c>; + assigned-clocks = <0x01 0x02>; + assigned-clock-rates = <0x7754188>; + + ethernet-phy@0 { + reg = <0x00>; + phandle = <0x0c>; + }; + }; + + pwm@10020000 { + compatible = "sifive,fu740-c000-pwm", "sifive,pwm0"; + reg = <0x00 0x10020000 0x00 0x1000>; + interrupt-parent = <0x0a>; + interrupts = <0x2c 0x2d 0x2e 0x2f>; + clocks = <0x01 0x07>; + #pwm-cells = <0x03>; + status = "okay"; + }; + + pwm@10021000 { + compatible = "sifive,fu740-c000-pwm", "sifive,pwm0"; + reg = <0x00 0x10021000 0x00 0x1000>; + interrupt-parent = <0x0a>; + interrupts = <0x30 0x31 0x32 0x33>; + clocks = <0x01 0x07>; + #pwm-cells = <0x03>; + status = "okay"; + }; + + cache-controller@2010000 { + compatible = "sifive,fu740-c000-ccache", "cache"; + cache-block-size = <0x40>; + cache-level = <0x02>; + cache-sets = <0x800>; + cache-size = <0x200000>; + cache-unified; + interrupt-parent = <0x0a>; + interrupts = <0x13 0x15 0x16 0x14>; + reg = <0x00 0x2010000 0x00 0x1000>; + status = "okay"; + phandle = <0x02>; + }; + + gpio@10060000 { + compatible = "sifive,fu740-c000-gpio", "sifive,gpio0"; + interrupt-parent = <0x0a>; + interrupts = <0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x20 0x21 0x22 0x23 0x24 0x25 0x26>; + reg = <0x00 0x10060000 0x00 0x1000>; + gpio-controller; + #gpio-cells = <0x02>; + interrupt-controller; + #interrupt-cells = <0x02>; + clocks = <0x01 0x07>; + status = "okay"; + u-boot,dm-spl; + phandle = <0x0b>; + }; + + pcie@e00000000 { + #address-cells = <0x03>; + #interrupt-cells = <0x01>; + #num-lanes = <0x08>; + #size-cells = <0x02>; + compatible = "sifive,fu740-pcie"; + reg = <0x0e 0x00 0x01 0x00 0x0d 0xf0000000 0x00 0x10000000 0x00 0x100d0000 0x00 0x1000>; + reg-names = "dbi", "config", "mgmt"; + device_type = "pci"; + dma-coherent; + bus-range = <0x00 0xff>; + ranges = <0x81000000 0x00 0x60080000 0x00 0x60080000 0x00 0x10000 0x82000000 0x00 0x60090000 0x00 0x60090000 0x00 0xff70000 0x82000000 0x00 0x70000000 0x00 0x70000000 0x00 0x1000000 0xc3000000 0x20 0x00 0x20 0x00 0x20 0x00>; + num-lanes = <0x08>; + interrupts = <0x38 0x39 0x3a 0x3b 0x3c 0x3d 0x3e 0x3f 0x40>; + interrupt-names = "msi", "inta", "intb", "intc", "intd"; + interrupt-parent = <0x0a>; + interrupt-map-mask = <0x00 0x00 0x00 0x07>; + interrupt-map = <0x00 0x00 0x00 0x01 0x0a 0x39 0x00 0x00 0x00 0x02 0x0a 0x3a 0x00 0x00 0x00 0x03 0x0a 0x3b 0x00 0x00 0x00 0x04 0x0a 0x3c>; + pwren-gpios = <0x0b 0x05 0x00>; + reset-gpios = <0x0b 0x08 0x00>; + clocks = <0x01 0x08>; + clock-names = "pcieaux"; + resets = <0x01 0x04>; + reset-names = "rst_n"; + status = "okay"; + }; + + clint@2000000 { + compatible = "riscv,clint0"; + interrupts-extended = <0x03 0x03 0x03 0x07 0x04 0x03 0x04 0x07 0x05 0x03 0x05 0x07 0x06 0x03 0x06 0x07 0x07 0x03 0x07 0x07>; + reg = <0x00 0x2000000 0x00 0x10000>; + u-boot,dm-spl; + clocks = <0x09>; + }; + + dmc@100b0000 { + compatible = "sifive,fu740-c000-ddr"; + reg = <0x00 0x100b0000 0x00 0x800 0x00 0x100b2000 0x00 0x2000 0x00 0x100b8000 0x00 0x1000>; + clocks = <0x01 0x01>; + clock-frequency = <0x37a1894c>; + u-boot,dm-spl; + sifive,ddr-params = <0xa00 0x00 0x00 0x00 0x00 0x00 0x0a 0x2d362 0x71073 0xa1c0255 0x1c1c0400 0x404c90b 0x2b050405 0xd0c081e 0x8090914 0xfde718 0x180a05 0x8b130d 0x1000118 0xd032001 0x00 0x101 0x00 0xa000000 0x00 0x1450100 0x1c36 0x05 0x170006 0x14e0400 0x3010000 0xa0e00 0x4030200 0x31f 0x70004 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x424 0x201 0x1008 0x00 0x200 0x800 0x481 0x400 0x424 0x201 0x1008 0x00 0x200 0x800 0x481 0x400 0x1010000 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x03 0x00 0x00 0x00 0x00 0x1000000 0x40000 0x800200 0x200 0x40 0x1000100 0xa000002 0x101ffff 0x1010101 0x1010101 0x10b 0xc03 0x00 0x00 0x00 0x00 0x30300 0x00 0x10101 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x2010102 0x108070d 0x5050300 0x4000503 0x00 0x00 0x00 0x00 0x280d0000 0x1000000 0x00 0x30001 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x1000000 0x01 0x100 0x10303 0x67676701 0x67676767 0x67676767 0x67676767 0x67676767 0x67676767 0x67676767 0x67676767 0x67676767 0x1000067 0x01 0x101 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x00 0x7fffff 0x00 0x7fffff 0x00 0x7fffff 0x00 0x7fffff 0x00 0x7fffff 0x00 0x7fffff 0x00 0x7fffff 0x00 0x37fffff 0xffffffff 0xf000f 0xffff03 0xfffff 0x3000f 0xffffffff 0xf000f 0xffff03 0xfffff 0x3000f 0xffffffff 0xf000f 0xffff03 0xfffff 0x3000f 0xffffffff 0xf000f 0xffff03 0xfffff 0x6407000f 0x1640001 0x00 0x00 0x1800 0x386c05 0x2000200 0x2000200 0x386c 0x23438 0x2020d0f 0x140303 0x00 0x00 0x1403 0x00 0x00 0x00 0x00 0xc010000 0x08 0x1375642 0x4c008 0xda 0x00 0x00 0x10000 0x1dddd90 0x1dddd90 0x1030001 0x1000000 0xc00000 0x07 0x00 0x00 0x4000408 0x408 0xe4e400 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x200000 0x00 0x00 0x00 0x00 0x00 0x00 0x2800280 0x2800280 0x2800280 0x2800280 0x280 0x00 0x00 0x00 0x00 0x00 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x100da 0x1ff0010 0x00 0x00 0x02 0x51313152 0x80013130 0x2000080 0x100001 0xc064208 0xf0c0f 0x1000140 0x0c 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x40263571 0x4c008 0xda 0x00 0x00 0x10000 0x1dddd90 0x1dddd90 0x1030001 0x1000000 0xc00000 0x07 0x00 0x00 0x4000408 0x408 0xe4e400 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x200000 0x00 0x00 0x00 0x00 0x00 0x00 0x2800280 0x2800280 0x2800280 0x2800280 0x280 0x00 0x00 0x00 0x00 0x00 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x100da 0x1ff0010 0x00 0x00 0x02 0x51313152 0x80013130 0x2000080 0x100001 0xc064208 0xf0c0f 0x1000140 0x0c 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x46052371 0x4c008 0xda 0x00 0x00 0x10000 0x1dddd90 0x1dddd90 0x1030001 0x1000000 0xc00000 0x07 0x00 0x00 0x4000408 0x408 0xe4e400 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x200000 0x00 0x00 0x00 0x00 0x00 0x00 0x2800280 0x2800280 0x2800280 0x2800280 0x280 0x00 0x00 0x00 0x00 0x00 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x100da 0x1ff0010 0x00 0x00 0x02 0x51313152 0x80013130 0x2000080 0x100001 0xc064208 0xf0c0f 0x1000140 0x0c 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x37651240 0x4c008 0xda 0x00 0x00 0x10000 0x1dddd90 0x1dddd90 0x1030001 0x1000000 0xc00000 0x07 0x00 0x00 0x4000408 0x408 0xe4e400 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x200000 0x00 0x00 0x00 0x00 0x00 0x00 0x2800280 0x2800280 0x2800280 0x2800280 0x280 0x00 0x00 0x00 0x00 0x00 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x100da 0x1ff0010 0x00 0x00 0x02 0x51313152 0x80013130 0x2000080 0x100001 0xc064208 0xf0c0f 0x1000140 0x0c 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x34216750 0x4c008 0xda 0x00 0x00 0x10000 0x1dddd90 0x1dddd90 0x1030001 0x1000000 0xc00000 0x07 0x00 0x00 0x4000408 0x408 0xe4e400 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x200000 0x00 0x00 0x00 0x00 0x00 0x00 0x2800280 0x2800280 0x2800280 0x2800280 0x280 0x00 0x00 0x00 0x00 0x00 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x100da 0x1ff0010 0x00 0x00 0x02 0x51313152 0x80013130 0x2000080 0x100001 0xc064208 0xf0c0f 0x1000140 0x0c 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x35176402 0x4c008 0xda 0x00 0x00 0x10000 0x1dddd90 0x1dddd90 0x1030001 0x1000000 0xc00000 0x07 0x00 0x00 0x4000408 0x408 0xe4e400 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x200000 0x00 0x00 0x00 0x00 0x00 0x00 0x2800280 0x2800280 0x2800280 0x2800280 0x280 0x00 0x00 0x00 0x00 0x00 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x100da 0x1ff0010 0x00 0x00 0x02 0x51313152 0x80013130 0x2000080 0x100001 0xc064208 0xf0c0f 0x1000140 0x0c 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x10526347 0x4c008 0xda 0x00 0x00 0x10000 0x1dddd90 0x1dddd90 0x1030001 0x1000000 0xc00000 0x07 0x00 0x00 0x4000408 0x408 0xe4e400 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x200000 0x00 0x00 0x00 0x00 0x00 0x00 0x2800280 0x2800280 0x2800280 0x2800280 0x280 0x00 0x00 0x00 0x00 0x00 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x100da 0x1ff0010 0x00 0x00 0x02 0x51313152 0x80013130 0x2000080 0x100001 0xc064208 0xf0c0f 0x1000140 0x0c 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x41753260 0x4c008 0xda 0x00 0x00 0x10000 0x1dddd90 0x1dddd90 0x1030001 0x1000000 0xc00000 0x07 0x00 0x00 0x4000408 0x408 0xe4e400 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x200000 0x00 0x00 0x00 0x00 0x00 0x00 0x2800280 0x2800280 0x2800280 0x2800280 0x280 0x00 0x00 0x00 0x00 0x00 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x100da 0x1ff0010 0x00 0x00 0x02 0x51313152 0x80013130 0x2000080 0x100001 0xc064208 0xf0c0f 0x1000140 0x0c 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x76543210 0x4c008 0xda 0x00 0x00 0x10000 0x1665555 0x1665555 0x1030001 0x1000000 0xc00000 0x07 0x00 0x00 0x4000408 0x408 0xe4e400 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x200000 0x00 0x00 0x00 0x00 0x00 0x00 0x2800280 0x2800280 0x2800280 0x2800280 0x280 0x00 0x00 0x00 0x00 0x00 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x100da 0x1ff0010 0x00 0x00 0x02 0x51313152 0x80013130 0x2000080 0x100001 0xc064208 0xf0c0f 0x1000140 0x0c 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x50000 0x00 0x00 0x00 0x100 0x00 0x00 0x506401 0x1221102 0x122 0x00 0xb1f00 0xb1f0b1f 0xb1f0b1f 0xb1f0b1f 0xb1f0b1f 0xb00 0x42080010 0x1000100 0x1000100 0x1000100 0x1000100 0x00 0x00 0x00 0x00 0x00 0x803 0x223fff00 0x8ff 0x57f 0x57f 0x37fff 0x37fff 0x4410 0x4410 0x4410 0x4410 0x4410 0x111 0x111 0x00 0x00 0x00 0x4000000 0x00 0x00 0x108 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x20100 0x00 0x00>; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x00 0x80000000 0x04 0x00>; + u-boot,dm-spl; + }; + + hfclk { + #clock-cells = <0x00>; + compatible = "fixed-clock"; + clock-frequency = <0x18cba80>; + clock-output-names = "hfclk"; + u-boot,dm-spl; + phandle = <0x08>; + }; + + rtcclk { + #clock-cells = <0x00>; + compatible = "fixed-clock"; + clock-frequency = <0xf4240>; + clock-output-names = "rtcclk"; + u-boot,dm-spl; + phandle = <0x09>; + }; + + gpio-poweroff { + compatible = "gpio-poweroff"; + gpios = <0x0b 0x02 0x01>; + }; + + binman { + multiple-images; + + itb { + filename = "u-boot.itb"; + + fit { + description = "Configuration to load OpenSBI before U-Boot"; + #address-cells = <0x01>; + fit,fdt-list = "of-list"; + + images { + + uboot { + description = "U-Boot"; + type = "standalone"; + os = "U-Boot"; + arch = "riscv"; + compression = "none"; + load = <0x80200000>; + + blob-ext { + filename = "u-boot-nodtb.bin"; + }; + }; + + opensbi { + description = "OpenSBI fw_dynamic Firmware"; + type = "firmware"; + os = "opensbi"; + arch = "riscv"; + compression = "none"; + load = <0x80000000>; + entry = <0x80000000>; + + opensbi { + filename = "fw_dynamic.bin"; + }; + }; + + @fdt-SEQ { + description = "NAME"; + type = "flat_dt"; + compression = "none"; + }; + }; + + configurations { + default = "conf-1"; + + @conf-SEQ { + description = "NAME"; + firmware = "opensbi"; + loadables = "uboot"; + fdt = "fdt-SEQ"; + }; + }; + }; + }; + }; +}; diff --git a/src/lib.rs b/src/lib.rs index f7ab02e..c5333c3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,6 +20,7 @@ extern crate alloc; pub mod de; pub mod error; +pub mod utils; mod common; mod de_mut; diff --git a/src/utils/mod.rs b/src/utils/mod.rs new file mode 100644 index 0000000..189cea1 --- /dev/null +++ b/src/utils/mod.rs @@ -0,0 +1,121 @@ +use crate::buildin::Node; + +pub trait DeviceTreeTraversal { + fn find(&self, _path: &str) -> Option { + None + } + fn search(&self, _func: &mut F) + where + F: FnMut(&Node), + { + } +} + +impl<'de> DeviceTreeTraversal for Node<'de> { + /// Try to get a node by path + fn find(&self, path: &str) -> Option { + // Direct return root node + let mut current_node = Some(self.clone()); + if path == "/" { + return current_node; + } + let (root, path) = path.split_at(1); + if root != "/" { + return None; + } + // Split path with / and find each level + for current_name in path.split('/') { + let node = match current_node.clone() { + Some(node) => node, + None => break, + }; + let mut nodes = match node.nodes() { + Some(nodes) => nodes, + None => { + current_node = None; + break; + } + }; + let next_node_iter = nodes.find(|x| x.get_full_name() == current_name); + match next_node_iter { + None => current_node = None, + Some(iter) => { + let next_node = iter.deserialize::(); + current_node = Some(next_node); + } + } + } + current_node + } + + /// use depth-first search to traversal the tree, and exec func for each node + fn search(&self, func: &mut F) + where + F: FnMut(&Node), + { + func(self); + if let Some(nodes) = self.nodes() { + for node in nodes { + let node = node.deserialize::(); + node.search(func); + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + buildin::{Node, StrSeq}, + from_raw_mut, Dtb, DtbPtr, + }; + static RAW_DEVICE_TREE: &'static [u8] = + include_bytes!("../../examples/hifive-unmatched-a00.dtb"); + const BUFFER_SIZE: usize = RAW_DEVICE_TREE.len(); + #[repr(align(8))] + struct AlignedBuffer { + pub data: [u8; RAW_DEVICE_TREE.len()], + } + #[test] + fn test_search() { + let mut aligned_data: Box = Box::new(AlignedBuffer { + data: [0; BUFFER_SIZE], + }); + aligned_data.data[..BUFFER_SIZE].clone_from_slice(RAW_DEVICE_TREE); + let mut slice = aligned_data.data.to_vec(); + let ptr = DtbPtr::from_raw(slice.as_mut_ptr()).unwrap(); + let dtb = Dtb::from(ptr).share(); + + let node: Node = from_raw_mut(&dtb).unwrap(); + let mut count = 0; + let mut closure = |_node: &Node| count += 1; + node.search(&mut closure); + assert_eq!(count, 70); + } + #[test] + fn test_find() { + let mut aligned_data: Box = Box::new(AlignedBuffer { + data: [0; BUFFER_SIZE], + }); + aligned_data.data[..BUFFER_SIZE].clone_from_slice(RAW_DEVICE_TREE); + let mut slice = aligned_data.data.to_vec(); + let ptr = DtbPtr::from_raw(slice.as_mut_ptr()).unwrap(); + let dtb = Dtb::from(ptr).share(); + + let node: Node = from_raw_mut(&dtb).unwrap(); + let node = node.find("/chosen").unwrap(); + let result = node + .props() + .unwrap() + .find(|prop| prop.get_name() == "stdout-path"); + match result { + Some(iter) => { + if iter.deserialize::().iter().next().unwrap() != "serial0" { + panic!("wrong /chosen/stdout-path value"); + } + } + None => panic!("failed to find /chosen/stdout-path"), + } + } +} From a76362d7bd34d7a8b966f03c2c1fa4916e16d76e Mon Sep 17 00:00:00 2001 From: Woshiluo Luo Date: Tue, 29 Oct 2024 21:29:39 +0800 Subject: [PATCH 03/10] fix: clippy Signed-off-by: Woshiluo Luo --- src/de.rs | 2 +- src/utils/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/de.rs b/src/de.rs index b6dd1b4..bd2629f 100644 --- a/src/de.rs +++ b/src/de.rs @@ -77,7 +77,7 @@ where let total_size = u32::from_be(header.total_size); let raw_data_len = (total_size - HEADER_LEN) as usize; - let ans_ptr = core::ptr::from_raw_parts(ptr as *const u8, raw_data_len); + let ans_ptr = core::ptr::from_raw_parts(ptr, raw_data_len); let device_tree: &DeviceTree = &*ans_ptr; let tags = device_tree.tags(); let mut d = Deserializer { diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 189cea1..d2b1dcf 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -11,7 +11,7 @@ pub trait DeviceTreeTraversal { } } -impl<'de> DeviceTreeTraversal for Node<'de> { +impl DeviceTreeTraversal for Node<'_> { /// Try to get a node by path fn find(&self, path: &str) -> Option { // Direct return root node From c88622a3b3d60854414d5c6a333de6a3128077ab Mon Sep 17 00:00:00 2001 From: Woshiluo Luo Date: Tue, 29 Oct 2024 21:36:37 +0800 Subject: [PATCH 04/10] fix: remove redundant trait Signed-off-by: Woshiluo Luo --- src/utils/mod.rs | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/src/utils/mod.rs b/src/utils/mod.rs index d2b1dcf..59158ee 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,19 +1,8 @@ use crate::buildin::Node; -pub trait DeviceTreeTraversal { - fn find(&self, _path: &str) -> Option { - None - } - fn search(&self, _func: &mut F) - where - F: FnMut(&Node), - { - } -} - -impl DeviceTreeTraversal for Node<'_> { +impl Node<'_> { /// Try to get a node by path - fn find(&self, path: &str) -> Option { + pub fn find(&self, path: &str) -> Option { // Direct return root node let mut current_node = Some(self.clone()); if path == "/" { @@ -49,7 +38,7 @@ impl DeviceTreeTraversal for Node<'_> { } /// use depth-first search to traversal the tree, and exec func for each node - fn search(&self, func: &mut F) + pub fn search(&self, func: &mut F) where F: FnMut(&Node), { From 833ef96dd154f4d7e311084fdaf6b1bdcc0dc323 Mon Sep 17 00:00:00 2001 From: Woshiluo Luo Date: Wed, 30 Oct 2024 01:42:40 +0800 Subject: [PATCH 05/10] refactor: merge BorrowedValueDeserializer and StructDeserializer as ValueDeserializer Signed-off-by: Woshiluo Luo --- src/de_mut/data.rs | 227 ++++++++++++++++++++++++++++--------- src/de_mut/mod.rs | 73 +++++++----- src/de_mut/node.rs | 109 ++++++++---------- src/de_mut/node_seq.rs | 7 +- src/de_mut/struct.rs | 250 ----------------------------------------- 5 files changed, 262 insertions(+), 404 deletions(-) delete mode 100644 src/de_mut/struct.rs diff --git a/src/de_mut/data.rs b/src/de_mut/data.rs index 970906a..ef02bd0 100644 --- a/src/de_mut/data.rs +++ b/src/de_mut/data.rs @@ -1,13 +1,62 @@ -use super::{DtError, PropCursor, RefDtb, RegConfig}; -use serde::de; +use super::BodyCursor; +use super::{DtError, PropCursor, RefDtb, RegConfig}; -pub(super) struct BorrowedValueDeserializer<'de> { +use core::marker::PhantomData; +use serde::{de, Deserialize}; + +#[derive(Clone, Debug)] +pub(super) enum ValueCursor { + Prop(PropCursor), + Body(BodyCursor), +} + +#[derive(Clone)] +pub(super) struct ValueDeserializer<'de> { pub dtb: RefDtb<'de>, pub reg: RegConfig, - pub cursor: PropCursor, + pub body_cursor: BodyCursor, + pub cursor: ValueCursor, } -impl<'de> de::Deserializer<'de> for &mut BorrowedValueDeserializer<'de> { +impl<'de> Deserialize<'de> for ValueDeserializer<'_> { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + struct Visitor<'de, 'b> { + marker: PhantomData>, + lifetime: PhantomData<&'de ()>, + } + impl<'de, 'b> de::Visitor<'de> for Visitor<'de, 'b> { + type Value = ValueDeserializer<'b>; + + fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { + write!(formatter, "struct ValueDeserializer") + } + + fn visit_newtype_struct(self, deserializer: D) -> Result + where + D: de::Deserializer<'de>, + { + Ok(unsafe { + (*(core::ptr::addr_of!(deserializer) as *const _ as *const &ValueDeserializer)) + .clone() + }) + } + } + + serde::Deserializer::deserialize_newtype_struct( + deserializer, + super::VALUE_DESERIALIZER_NAME, + Visitor { + marker: PhantomData, + lifetime: PhantomData, + }, + ) + } +} + +impl<'de> de::Deserializer<'de> for &mut ValueDeserializer<'de> { type Error = DtError; fn deserialize_any(self, _visitor: V) -> Result @@ -21,14 +70,17 @@ impl<'de> de::Deserializer<'de> for &mut BorrowedValueDeserializer<'de> { where V: de::Visitor<'de>, { - let val = self.cursor.map_on(self.dtb, |data| { - if data.is_empty() { - true - } else { - todo!("&[u8] -> bool") - } - }); - visitor.visit_bool(val) + if let ValueCursor::Prop(cursor) = self.cursor { + let val = cursor.map_on(self.dtb, |data| { + if data.is_empty() { + true + } else { + todo!("&[u8] -> bool") + } + }); + return visitor.visit_bool(val); + } + unreachable!("Node -> bool"); } fn deserialize_i8(self, _visitor: V) -> Result @@ -77,7 +129,10 @@ impl<'de> de::Deserializer<'de> for &mut BorrowedValueDeserializer<'de> { where V: de::Visitor<'de>, { - visitor.visit_u32(self.cursor.map_u32_on(self.dtb)?) + if let ValueCursor::Prop(cursor) = self.cursor { + return visitor.visit_u32(cursor.map_u32_on(self.dtb)?); + } + unreachable!("node -> u32"); } fn deserialize_u64(self, _visitor: V) -> Result @@ -108,12 +163,11 @@ impl<'de> de::Deserializer<'de> for &mut BorrowedValueDeserializer<'de> { unreachable!("char") } - fn deserialize_str(self, visitor: V) -> Result + fn deserialize_str(self, _visitor: V) -> Result where V: de::Visitor<'de>, { - let data = self.cursor.data_on(self.dtb); - visitor.visit_borrowed_str(unsafe { core::str::from_utf8_unchecked(data) }) + unreachable!("str"); } fn deserialize_string(self, _visitor: V) -> Result @@ -127,8 +181,11 @@ impl<'de> de::Deserializer<'de> for &mut BorrowedValueDeserializer<'de> { where V: de::Visitor<'de>, { - let data = self.cursor.data_on(self.dtb); - visitor.visit_borrowed_bytes(data) + if let ValueCursor::Prop(cursor) = self.cursor { + let data = cursor.data_on(self.dtb); + return visitor.visit_borrowed_bytes(data); + } + unreachable!("node -> bytes"); } fn deserialize_byte_buf(self, _visitor: V) -> Result @@ -142,11 +199,16 @@ impl<'de> de::Deserializer<'de> for &mut BorrowedValueDeserializer<'de> { where V: de::Visitor<'de>, { - let data = self.cursor.data_on(self.dtb); - if data.is_empty() { - visitor.visit_none() - } else { - visitor.visit_some(self) + match self.cursor { + ValueCursor::Prop(cursor) => { + let data = cursor.data_on(self.dtb); + if data.is_empty() { + visitor.visit_none() + } else { + visitor.visit_some(self) + } + } + ValueCursor::Body(_) => visitor.visit_some(self), } } @@ -176,33 +238,39 @@ impl<'de> de::Deserializer<'de> for &mut BorrowedValueDeserializer<'de> { where V: de::Visitor<'de>, { - match name { - "StrSeq" => { - let inner = super::str_seq::Inner { - dtb: self.dtb, - cursor: self.cursor, - }; - visitor.visit_borrowed_bytes(unsafe { - core::slice::from_raw_parts( - &inner as *const _ as *const u8, - core::mem::size_of_val(&inner), - ) - }) - } - "Reg" => { - let inner = super::reg::Inner { - dtb: self.dtb, - reg: self.reg, - cursor: self.cursor, - }; - visitor.visit_borrowed_bytes(unsafe { - core::slice::from_raw_parts( - &inner as *const _ as *const u8, - core::mem::size_of_val(&inner), - ) - }) - } - _ => visitor.visit_newtype_struct(self), + if name == super::VALUE_DESERIALIZER_NAME { + return visitor.visit_newtype_struct(self); + } + match self.cursor { + ValueCursor::Prop(cursor) => match name { + "StrSeq" => { + let inner = super::str_seq::Inner { + dtb: self.dtb, + cursor, + }; + visitor.visit_borrowed_bytes(unsafe { + core::slice::from_raw_parts( + &inner as *const _ as *const u8, + core::mem::size_of_val(&inner), + ) + }) + } + "Reg" => { + let inner = super::reg::Inner { + dtb: self.dtb, + reg: self.reg, + cursor, + }; + visitor.visit_borrowed_bytes(unsafe { + core::slice::from_raw_parts( + &inner as *const _ as *const u8, + core::mem::size_of_val(&inner), + ) + }) + } + _ => visitor.visit_newtype_struct(self), + }, + ValueCursor::Body(_) => visitor.visit_newtype_struct(self), } } @@ -232,23 +300,39 @@ impl<'de> de::Deserializer<'de> for &mut BorrowedValueDeserializer<'de> { unreachable!("tuple_struct") } - fn deserialize_map(self, _visitor: V) -> Result + fn deserialize_map(self, visitor: V) -> Result where V: de::Visitor<'de>, { - unreachable!("map") + use super::{StructAccess, Temp}; + if let ValueCursor::Body(cursor) = self.cursor { + return visitor.visit_map(StructAccess { + fields: None, + temp: Temp::Node(self.body_cursor, cursor), + de: self, + }); + }; + unreachable!("Prop -> map") } fn deserialize_struct( self, _name: &'static str, - _fields: &'static [&'static str], - _visitor: V, + fields: &'static [&'static str], + visitor: V, ) -> Result where V: de::Visitor<'de>, { - unreachable!("struct {_name} {_fields:?}") + use super::{StructAccess, Temp}; + if let ValueCursor::Body(cursor) = self.cursor { + return visitor.visit_map(StructAccess { + fields: Some(fields), + temp: Temp::Node(self.body_cursor, cursor), + de: self, + }); + }; + unreachable!("Prop -> struct {_name} {fields:?}") } fn deserialize_enum( @@ -277,3 +361,34 @@ impl<'de> de::Deserializer<'de> for &mut BorrowedValueDeserializer<'de> { unreachable!("ignored_any") } } + +impl ValueDeserializer<'_> { + #[inline] + pub fn move_next(&mut self) -> super::Cursor { + if let ValueCursor::Body(ref mut cursor) = self.cursor { + return cursor.move_on(self.dtb); + }; + unreachable!("move_on prop cursor"); + } + #[inline] + pub fn step_n(&mut self, n: usize) { + if let ValueCursor::Body(ref mut cursor) = self.cursor { + return cursor.step_n(n); + }; + unreachable!("step_n prop cursor"); + } + #[inline] + pub fn is_complete_on(&self) -> bool { + if let ValueCursor::Body(cursor) = self.cursor { + return cursor.is_complete_on(self.dtb); + }; + unreachable!("is_complete_on prop cursor"); + } + #[inline] + pub fn file_index_on(&self) -> usize { + if let ValueCursor::Body(cursor) = self.cursor { + return cursor.file_index_on(self.dtb); + }; + unreachable!("file_index_on prop cursor"); + } +} diff --git a/src/de_mut/mod.rs b/src/de_mut/mod.rs index e88dd24..aa84695 100644 --- a/src/de_mut/mod.rs +++ b/src/de_mut/mod.rs @@ -11,19 +11,19 @@ mod node; mod node_seq; mod reg; mod str_seq; -mod r#struct; +// mod r#struct; mod structs; +const VALUE_DESERIALIZER_NAME: &str = "$serde_device_tree$de_mut$ValueDeserializer"; + pub use structs::{Dtb, DtbPtr}; pub mod buildin { pub use super::{node::Node, node_seq::NodeSeq, reg::Reg, str_seq::StrSeq}; } use cursor::{BodyCursor, Cursor, GroupCursor, PropCursor}; -use data::BorrowedValueDeserializer; +use data::{ValueCursor, ValueDeserializer}; use group::GroupDeserializer; -// use node::NodeDeserializer; -use r#struct::StructDeserializer; use reg::RegConfig; use structs::{RefDtb, StructureBlock, BLOCK_LEN}; @@ -37,28 +37,27 @@ where { // 根节点的名字固定为空字符串, // 从一个跳过根节点名字的光标初始化解析器。 - let mut d = StructDeserializer { + let mut d = ValueDeserializer { dtb, reg: RegConfig::DEFAULT, - cursor: BodyCursor::ROOT, + body_cursor: BodyCursor::ROOT, + cursor: ValueCursor::Body(BodyCursor::ROOT), }; T::deserialize(&mut d).and_then(|t| { // 解析必须完成 - if d.cursor.is_complete_on(dtb) { + if d.is_complete_on() { Ok(t) } else { - Err(DtError::deserialize_not_complete( - d.cursor.file_index_on(d.dtb), - )) + Err(DtError::deserialize_not_complete(d.file_index_on())) } }) } /// 结构体解析状态。 struct StructAccess<'de, 'b> { - fields: &'static [&'static str], + fields: Option<&'static [&'static str]>, temp: Temp, - de: &'b mut StructDeserializer<'de>, + de: &'b mut ValueDeserializer<'de>, } /// 用于跨键-值传递的临时变量。 @@ -66,9 +65,9 @@ struct StructAccess<'de, 'b> { /// 解析键(名字)时将确定值类型,保存 `Temp` 类型的状态。 /// 根据状态分发值解析器。 enum Temp { - Node(BodyCursor), + Node(BodyCursor, BodyCursor), Group(GroupCursor, usize, usize), - Prop(PropCursor), + Prop(BodyCursor, PropCursor), } impl<'de> de::MapAccess<'de> for StructAccess<'de, '_> { @@ -78,19 +77,29 @@ impl<'de> de::MapAccess<'de> for StructAccess<'de, '_> { where K: de::DeserializeSeed<'de>, { + let check_contains = |name: &str| -> bool { + match self.fields { + Some(fields) => fields.contains(&name), + None => true, + } + }; let name = loop { + let origin_cursor = match self.de.cursor { + ValueCursor::Body(cursor) => cursor, + _ => unreachable!("map access's cursor should always be body cursor"), + }; match self.de.move_next() { // 子节点名字 Cursor::Title(c) => { let (name, _) = c.split_on(self.de.dtb); let pre_len = name.as_bytes().iter().take_while(|b| **b != b'@').count(); - // 子节点名字不带 @ - if pre_len == name.as_bytes().len() { + // 子节点名字不带 @ 或正在解析 Node 类型 + if pre_len == name.as_bytes().len() || check_contains(name) { let (node, next) = c.take_node_on(self.de.dtb, name); - self.de.cursor = next; - if self.fields.contains(&name) { - self.temp = Temp::Node(node); + self.de.cursor = ValueCursor::Body(next); + if check_contains(name) { + self.temp = Temp::Node(origin_cursor, node); break name; } } @@ -99,8 +108,8 @@ impl<'de> de::MapAccess<'de> for StructAccess<'de, '_> { let name_bytes = &name.as_bytes()[..pre_len]; let name = unsafe { core::str::from_utf8_unchecked(name_bytes) }; let (group, len, next) = c.take_group_on(self.de.dtb, name); - self.de.cursor = next; - if self.fields.contains(&name) { + self.de.cursor = ValueCursor::Body(next); + if check_contains(name) { self.temp = Temp::Group(group, len, name.len()); break name; } @@ -109,7 +118,7 @@ impl<'de> de::MapAccess<'de> for StructAccess<'de, '_> { // 属性条目 Cursor::Prop(c) => { let (name, next) = c.name_on(self.de.dtb); - self.de.cursor = next; + self.de.cursor = ValueCursor::Body(next); match name { "#address-cells" => { self.de.reg.address_cells = c.map_u32_on(self.de.dtb)?; @@ -119,14 +128,14 @@ impl<'de> de::MapAccess<'de> for StructAccess<'de, '_> { } _ => {} } - if self.fields.contains(&name) { - self.temp = Temp::Prop(c); + if check_contains(name) { + self.temp = Temp::Prop(origin_cursor, c); break name; } } // 截止符,结构体解析完成 Cursor::End => { - self.de.cursor.step_n(1); + self.de.step_n(1); return Ok(None); } } @@ -140,12 +149,13 @@ impl<'de> de::MapAccess<'de> for StructAccess<'de, '_> { V: de::DeserializeSeed<'de>, { match self.temp { - Temp::Node(cursor) => { + Temp::Node(origin_cursor, cursor) => { // 键是独立节点名字,递归 - seed.deserialize(&mut StructDeserializer { + seed.deserialize(&mut ValueDeserializer { dtb: self.de.dtb, - cursor, reg: self.de.reg, + body_cursor: origin_cursor, + cursor: ValueCursor::Body(cursor), }) } Temp::Group(cursor, len_item, len_name) => { @@ -158,12 +168,13 @@ impl<'de> de::MapAccess<'de> for StructAccess<'de, '_> { len_name, }) } - Temp::Prop(cursor) => { + Temp::Prop(origin_cursor, cursor) => { // 键是属性名字,构造属性反序列化器 - seed.deserialize(&mut BorrowedValueDeserializer { + seed.deserialize(&mut ValueDeserializer { dtb: self.de.dtb, + body_cursor: origin_cursor, reg: self.de.reg, - cursor, + cursor: ValueCursor::Prop(cursor), }) } } diff --git a/src/de_mut/node.rs b/src/de_mut/node.rs index d9e1eca..e6ca099 100644 --- a/src/de_mut/node.rs +++ b/src/de_mut/node.rs @@ -1,16 +1,13 @@ -use super::{ - BodyCursor, BorrowedValueDeserializer, Cursor, PropCursor, RefDtb, RegConfig, - StructDeserializer, -}; +use super::{BodyCursor, Cursor, PropCursor, RefDtb, RegConfig, ValueCursor, ValueDeserializer}; use core::fmt::Debug; use core::marker::PhantomData; +use serde::de::MapAccess; use serde::{de, Deserialize}; #[allow(unused)] #[derive(Clone)] pub struct Node<'de> { dtb: RefDtb<'de>, - cursor: BodyCursor, reg: RegConfig, props_start: Option, nodes_start: Option, @@ -43,57 +40,15 @@ pub struct PropIter<'de, 'b> { pub struct PropItem<'de> { dtb: RefDtb<'de>, reg: RegConfig, + body: BodyCursor, prop: PropCursor, name: &'de str, } impl<'de> Node<'de> { - unsafe fn covnert_from_struct_deseriallizer_pointer( - ptr: *const &StructDeserializer<'de>, - ) -> Self { - let struct_deseriallizer = &mut *(ptr as *mut &mut StructDeserializer<'de>); - let dtb = struct_deseriallizer.dtb; - let mut cursor = struct_deseriallizer.cursor; - let mut prop: Option = None; - let mut node: Option = None; - // TODO: 这里采用朴素的方式遍历块,可能会和 GroupCursor 带来的缓存冲突。 - // 可能需要一个更优雅的缓存方案或者放弃缓存。 - loop { - match cursor.move_on(dtb) { - Cursor::Title(c) => { - let (name, _) = c.split_on(dtb); - let (_, next) = c.take_node_on(dtb, name); - if node.is_none() { - node = Some(cursor) - } - cursor = next; - } - Cursor::Prop(c) => { - let (_, next) = c.name_on(dtb); - if prop.is_none() { - prop = Some(cursor) - } - cursor = next; - } - Cursor::End => { - cursor.move_next(dtb); - break; - } - } - } - struct_deseriallizer.cursor = cursor; - Node { - cursor: struct_deseriallizer.cursor, - reg: struct_deseriallizer.reg, - dtb: struct_deseriallizer.dtb, - props_start: prop, - nodes_start: node, - } - } - // TODO: Maybe use BTreeMap when have alloc /// 获得节点迭代器。 - pub const fn nodes<'b>(&'b self) -> Option> { + pub fn nodes<'b>(&'b self) -> Option> { match self.nodes_start { None => None, Some(node_cursor) => Some(NodeIter { @@ -105,7 +60,7 @@ impl<'de> Node<'de> { } /// 获得属性迭代器。 - pub const fn props<'b>(&'b self) -> Option> { + pub fn props<'b>(&'b self) -> Option> { match self.props_start { None => None, Some(node_cursor) => Some(PropIter { @@ -186,6 +141,7 @@ impl<'de> Iterator for PropIter<'de, '_> { let (name, next) = c.name_on(dtb); let res = Some(Self::Item { dtb, + body: self.cursor, reg: self.node.reg, prop: c, name, @@ -213,23 +169,45 @@ impl<'de> Deserialize<'de> for Node<'_> { fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { write!(formatter, "struct Node") } - - fn visit_newtype_struct(self, deserializer: D) -> Result + fn visit_map(self, mut access: M) -> Result where - D: de::Deserializer<'de>, + M: MapAccess<'de>, { - Ok(unsafe { - Node::covnert_from_struct_deseriallizer_pointer(core::ptr::addr_of!( - deserializer - ) - as *const &StructDeserializer) + // While there are entries remaining in the input, add them + // into our map. + let mut dtb: Option> = None; + let mut reg: Option = None; + let mut props_start: Option = None; + let mut nodes_start: Option = None; + while let Some((_, value)) = access.next_entry::<&str, ValueDeserializer<'b>>()? { + dtb = Some(value.dtb); + reg = Some(value.reg); + match value.cursor { + ValueCursor::Prop(_) => { + if props_start.is_none() { + props_start = Some(value.body_cursor); + } + } + ValueCursor::Body(_) => { + if nodes_start.is_none() { + nodes_start = Some(value.body_cursor); + } + } + } + } + + // TODO: May panic if a node have no children & prop + Ok(Node { + dtb: dtb.unwrap(), + reg: reg.unwrap(), + nodes_start, + props_start, }) } } - serde::Deserializer::deserialize_newtype_struct( + serde::Deserializer::deserialize_map( deserializer, - "Node", Visitor { marker: PhantomData, lifetime: PhantomData, @@ -241,10 +219,11 @@ impl<'de> Deserialize<'de> for Node<'_> { impl<'de> NodeItem<'de> { /// 反序列化一个节点的内容。 pub fn deserialize>(&self) -> T { - T::deserialize(&mut StructDeserializer { + T::deserialize(&mut ValueDeserializer { dtb: self.dtb, reg: self.reg, - cursor: self.node, + body_cursor: self.node, + cursor: ValueCursor::Body(self.node), }) .unwrap() } @@ -276,10 +255,12 @@ impl<'de> PropItem<'de> { self.name } pub fn deserialize>(&self) -> T { - T::deserialize(&mut BorrowedValueDeserializer { + use super::ValueCursor; + T::deserialize(&mut ValueDeserializer { dtb: self.dtb, reg: self.reg, - cursor: self.prop, + body_cursor: self.body, + cursor: ValueCursor::Prop(self.prop), }) .unwrap() } diff --git a/src/de_mut/node_seq.rs b/src/de_mut/node_seq.rs index d8f61e3..824e024 100644 --- a/src/de_mut/node_seq.rs +++ b/src/de_mut/node_seq.rs @@ -1,4 +1,4 @@ -use super::{BodyCursor, GroupCursor, RefDtb, RegConfig, StructDeserializer}; +use super::{BodyCursor, GroupCursor, RefDtb, RegConfig, ValueCursor, ValueDeserializer}; use crate::de_mut::GroupDeserializer; use core::{fmt::Debug, marker::PhantomData}; use serde::{de, Deserialize}; @@ -159,10 +159,11 @@ impl NodeSeqItem<'_> { impl<'de> NodeSeqItem<'de> { /// 反序列化一个节点的内容。 pub fn deserialize>(&self) -> T { - T::deserialize(&mut StructDeserializer { + T::deserialize(&mut ValueDeserializer { dtb: self.dtb, reg: self.reg, - cursor: self.body, + body_cursor: self.body, + cursor: ValueCursor::Body(self.body), }) .unwrap() } diff --git a/src/de_mut/struct.rs b/src/de_mut/struct.rs deleted file mode 100644 index 7c81542..0000000 --- a/src/de_mut/struct.rs +++ /dev/null @@ -1,250 +0,0 @@ -use super::{BodyCursor, Cursor, DtError, RefDtb, RegConfig, StructAccess, Temp}; -use serde::de; - -#[derive(Clone)] -pub(super) struct StructDeserializer<'de> { - pub dtb: RefDtb<'de>, - pub reg: RegConfig, - pub cursor: BodyCursor, -} - -impl<'de> de::Deserializer<'de> for &mut StructDeserializer<'de> { - type Error = DtError; - - fn deserialize_any(self, _visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!("any") - } - - fn deserialize_bool(self, _visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!("bool") - } - - fn deserialize_i8(self, _visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!("i8") - } - - fn deserialize_i16(self, _visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!("i16") - } - - fn deserialize_i32(self, _visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!("i32") - } - - fn deserialize_i64(self, _visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!("i64") - } - - fn deserialize_u8(self, _visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!("u8") - } - - fn deserialize_u16(self, _visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!("u16") - } - - fn deserialize_u32(self, _visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!("u32") - } - - fn deserialize_u64(self, _visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!("u64") - } - - fn deserialize_f32(self, _visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!("f32") - } - - fn deserialize_f64(self, _visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!("f64") - } - - fn deserialize_char(self, _visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!("char") - } - - fn deserialize_str(self, _visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!("str") - } - - fn deserialize_string(self, _visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!("string") - } - - fn deserialize_bytes(self, _visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!("bytes") - } - - fn deserialize_byte_buf(self, _visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!("byte_buf") - } - - fn deserialize_option(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - visitor.visit_some(self) - } - - fn deserialize_unit(self, _visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!("unit") - } - - fn deserialize_unit_struct( - self, - _name: &'static str, - _visitor: V, - ) -> Result - where - V: de::Visitor<'de>, - { - todo!("unit_struct") - } - - fn deserialize_newtype_struct( - self, - _name: &'static str, - visitor: V, - ) -> Result - where - V: de::Visitor<'de>, - { - visitor.visit_newtype_struct(self) - } - - fn deserialize_seq(self, _visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!("seq") - } - - fn deserialize_tuple(self, _len: usize, _visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!("tuple") - } - - fn deserialize_tuple_struct( - self, - _name: &'static str, - _len: usize, - _visitor: V, - ) -> Result - where - V: de::Visitor<'de>, - { - todo!("tuple_struct") - } - - fn deserialize_map(self, _visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!("map") - } - - fn deserialize_struct( - self, - _name: &'static str, - fields: &'static [&'static str], - visitor: V, - ) -> Result - where - V: de::Visitor<'de>, - { - visitor.visit_map(StructAccess { - fields, - temp: Temp::Node(self.cursor), - de: self, - }) - } - - fn deserialize_enum( - self, - _name: &'static str, - _variants: &'static [&'static str], - _visitor: V, - ) -> Result - where - V: de::Visitor<'de>, - { - todo!("enum") - } - - fn deserialize_identifier(self, _visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!("identifer") - } - - fn deserialize_ignored_any(self, _visitor: V) -> Result - where - V: de::Visitor<'de>, - { - todo!("ignored_any") - } -} - -impl StructDeserializer<'_> { - #[inline] - pub fn move_next(&mut self) -> Cursor { - self.cursor.move_on(self.dtb) - } -} From 55143de72f17833616c89e1fedaed9393b696a01 Mon Sep 17 00:00:00 2001 From: Woshiluo Luo Date: Thu, 31 Oct 2024 10:50:53 +0800 Subject: [PATCH 06/10] feat: add StructAcessType to ensure access type Signed-off-by: Woshiluo Luo --- src/de_mut/data.rs | 10 +++++----- src/de_mut/mod.rs | 32 ++++++++++++++++++++++++++++---- src/de_mut/node.rs | 6 ++++-- src/utils/mod.rs | 1 - 4 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/de_mut/data.rs b/src/de_mut/data.rs index ef02bd0..3420a51 100644 --- a/src/de_mut/data.rs +++ b/src/de_mut/data.rs @@ -4,7 +4,7 @@ use super::{DtError, PropCursor, RefDtb, RegConfig}; use core::marker::PhantomData; use serde::{de, Deserialize}; -#[derive(Clone, Debug)] +#[derive(Clone, Copy, Debug)] pub(super) enum ValueCursor { Prop(PropCursor), Body(BodyCursor), @@ -304,10 +304,10 @@ impl<'de> de::Deserializer<'de> for &mut ValueDeserializer<'de> { where V: de::Visitor<'de>, { - use super::{StructAccess, Temp}; + use super::{StructAccess, StructAccessType, Temp}; if let ValueCursor::Body(cursor) = self.cursor { return visitor.visit_map(StructAccess { - fields: None, + access_type: StructAccessType::Map(false), temp: Temp::Node(self.body_cursor, cursor), de: self, }); @@ -324,10 +324,10 @@ impl<'de> de::Deserializer<'de> for &mut ValueDeserializer<'de> { where V: de::Visitor<'de>, { - use super::{StructAccess, Temp}; + use super::{StructAccess, StructAccessType, Temp}; if let ValueCursor::Body(cursor) = self.cursor { return visitor.visit_map(StructAccess { - fields: Some(fields), + access_type: StructAccessType::Struct(fields), temp: Temp::Node(self.body_cursor, cursor), de: self, }); diff --git a/src/de_mut/mod.rs b/src/de_mut/mod.rs index aa84695..0f9a60e 100644 --- a/src/de_mut/mod.rs +++ b/src/de_mut/mod.rs @@ -53,9 +53,15 @@ where }) } +// For map type, we should send root item to trans dtb and reg +enum StructAccessType { + Map(bool), + Struct(&'static [&'static str]), +} + /// 结构体解析状态。 struct StructAccess<'de, 'b> { - fields: Option<&'static [&'static str]>, + access_type: StructAccessType, temp: Temp, de: &'b mut ValueDeserializer<'de>, } @@ -77,10 +83,17 @@ impl<'de> de::MapAccess<'de> for StructAccess<'de, '_> { where K: de::DeserializeSeed<'de>, { + if let StructAccessType::Map(flag) = self.access_type { + if !flag { + return seed + .deserialize(de::value::BorrowedStrDeserializer::new("/")) + .map(Some); + } + } let check_contains = |name: &str| -> bool { - match self.fields { - Some(fields) => fields.contains(&name), - None => true, + match self.access_type { + StructAccessType::Struct(fields) => fields.contains(&name), + _ => true, } }; let name = loop { @@ -148,6 +161,17 @@ impl<'de> de::MapAccess<'de> for StructAccess<'de, '_> { where V: de::DeserializeSeed<'de>, { + if let StructAccessType::Map(ref mut flag) = self.access_type { + if !*flag { + *flag = true; + return seed.deserialize(&mut ValueDeserializer { + dtb: self.de.dtb, + reg: self.de.reg, + body_cursor: self.de.body_cursor, + cursor: self.de.cursor, + }); + } + } match self.temp { Temp::Node(origin_cursor, cursor) => { // 键是独立节点名字,递归 diff --git a/src/de_mut/node.rs b/src/de_mut/node.rs index e6ca099..302229a 100644 --- a/src/de_mut/node.rs +++ b/src/de_mut/node.rs @@ -179,9 +179,12 @@ impl<'de> Deserialize<'de> for Node<'_> { let mut reg: Option = None; let mut props_start: Option = None; let mut nodes_start: Option = None; - while let Some((_, value)) = access.next_entry::<&str, ValueDeserializer<'b>>()? { + while let Some((key, value)) = access.next_entry::<&str, ValueDeserializer<'b>>()? { dtb = Some(value.dtb); reg = Some(value.reg); + if key == "/" { + continue; + } match value.cursor { ValueCursor::Prop(_) => { if props_start.is_none() { @@ -196,7 +199,6 @@ impl<'de> Deserialize<'de> for Node<'_> { } } - // TODO: May panic if a node have no children & prop Ok(Node { dtb: dtb.unwrap(), reg: reg.unwrap(), diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 59158ee..e9e7ba3 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -54,7 +54,6 @@ impl Node<'_> { #[cfg(test)] mod tests { - use super::*; use crate::{ buildin::{Node, StrSeq}, from_raw_mut, Dtb, DtbPtr, From 6b98e917536290e792190f27b422c3f8dfa0dd7b Mon Sep 17 00:00:00 2001 From: Woshiluo Luo Date: Thu, 31 Oct 2024 22:16:18 +0800 Subject: [PATCH 07/10] refactor: rewrite NodeSeq Signed-off-by: Woshiluo Luo --- src/de_mut/cursor.rs | 61 +-------- src/de_mut/data.rs | 50 ++++--- src/de_mut/group.rs | 251 ---------------------------------- src/de_mut/mod.rs | 92 +++++++++---- src/de_mut/node.rs | 26 ++-- src/de_mut/node_seq.rs | 113 ++++++++------- src/de_mut/structs.rs | 1 + src/utils/mod.rs | 2 +- tests/hifive-unmatched-a00.rs | 2 +- 9 files changed, 177 insertions(+), 421 deletions(-) delete mode 100644 src/de_mut/group.rs diff --git a/src/de_mut/cursor.rs b/src/de_mut/cursor.rs index 1ca239c..df27d65 100644 --- a/src/de_mut/cursor.rs +++ b/src/de_mut/cursor.rs @@ -7,7 +7,6 @@ pub(super) struct AnyCursor(usize, PhantomData); pub(super) type BodyCursor = AnyCursor; pub(super) type TitleCursor = AnyCursor; -pub(super) type GroupCursor = AnyCursor<Group>; pub(super) type PropCursor = AnyCursor<Prop>; pub(super) trait Type {} @@ -17,13 +16,10 @@ pub(super) struct Body {} #[derive(Clone, Copy, Debug)] pub(super) struct Title {} #[derive(Clone, Copy, Debug)] -pub(super) struct Group {} -#[derive(Clone, Copy, Debug)] pub(super) struct Prop {} impl Type for Body {} impl Type for Title {} -impl Type for Group {} impl Type for Prop {} pub enum MoveResult { @@ -107,7 +103,7 @@ impl BodyCursor { self.0 += 1; MoveResult::Others } - _ => todo!(), + _ => todo!("unknown block {}", structure[self.0]), } } @@ -149,10 +145,10 @@ impl TitleCursor { } /// 生成组光标。 - pub fn take_group_on(&self, dtb: RefDtb, name: &str) -> (GroupCursor, usize, BodyCursor) { + pub fn take_group_on(&self, dtb: RefDtb, name: &str) -> (BodyCursor, usize, BodyCursor) { let name_bytes = name.as_bytes(); let name_skip = align(name_bytes.len() + 1, BLOCK_LEN); - let group = AnyCursor::<Group>(self.0, PhantomData); + let group = AnyCursor::<Body>(self.0, PhantomData); let mut body = AnyCursor::<Body>(self.0 + 1 + name_skip, PhantomData); let mut len = 1; @@ -194,57 +190,6 @@ impl TitleCursor { } } -impl GroupCursor { - /// 读取缓存的下一项偏移。 - pub fn offset_on(&self, dtb: RefDtb) -> usize { - (dtb.borrow().structure[self.0].0 >> 8) as _ - } - - /// 利用缓存的名字长度取出名字。 - pub fn name_on<'a>(&self, dtb: RefDtb<'a>) -> (&'a [u8], BodyCursor) { - let structure = &dtb.borrow().structure; - let len_name = (structure[self.0].0 & 0xff) as usize; - let bytes = structure[self.0 + 1].lead_slice(len_name); - ( - bytes, - AnyCursor(self.0 + 1 + align(len_name + 1, BLOCK_LEN), PhantomData), - ) - } - - /// 初始化组反序列化。 - pub fn init_on(&self, dtb: RefDtb, len_item: usize, len_name: usize) { - let mut body = AnyCursor::<Body>(self.0, PhantomData); - for _ in 0..len_item { - let current = body.0; - let len_total = dtb.borrow().structure[current + 1] - .lead_slice(u16::MAX as _) - .iter() - .enumerate() - .skip(len_name + 1) - .find(|(_, b)| **b == b'\0') - .map(|(i, _)| i) - .unwrap(); - body.step_n(align(len_total, BLOCK_LEN)); - body.skip_str_on(dtb); - body.escape_from(dtb); - let off_next = body.0 - current; - dtb.borrow_mut().structure[current].0 = (off_next << 8 | len_total) as _; - } - } - - /// 组结构恢复原状。 - pub fn drop_on(&self, dtb: RefDtb, len_item: usize) { - use StructureBlock as B; - let structure = &mut *dtb.borrow_mut().structure; - let mut i = self.0; - for _ in 0..len_item { - let offset = (structure[i].0 >> 8) as usize; - structure[i] = B::NODE_BEGIN; - i += offset; - } - } -} - impl PropCursor { pub fn name_on<'a>(&self, dtb: RefDtb<'a>) -> (&'a str, BodyCursor) { let dtb = dtb.borrow(); diff --git a/src/de_mut/data.rs b/src/de_mut/data.rs index 3420a51..0074c1c 100644 --- a/src/de_mut/data.rs +++ b/src/de_mut/data.rs @@ -1,4 +1,4 @@ -use super::BodyCursor; +use super::{BodyCursor, Cursor}; use super::{DtError, PropCursor, RefDtb, RegConfig}; use core::marker::PhantomData; @@ -6,15 +6,14 @@ use serde::{de, Deserialize}; #[derive(Clone, Copy, Debug)] pub(super) enum ValueCursor { - Prop(PropCursor), + Prop(BodyCursor, PropCursor), Body(BodyCursor), } -#[derive(Clone)] +#[derive(Clone, Copy)] pub(super) struct ValueDeserializer<'de> { pub dtb: RefDtb<'de>, pub reg: RegConfig, - pub body_cursor: BodyCursor, pub cursor: ValueCursor, } @@ -39,8 +38,7 @@ impl<'de> Deserialize<'de> for ValueDeserializer<'_> { D: de::Deserializer<'de>, { Ok(unsafe { - (*(core::ptr::addr_of!(deserializer) as *const _ as *const &ValueDeserializer)) - .clone() + *(*(core::ptr::addr_of!(deserializer) as *const _ as *const &ValueDeserializer)) }) } } @@ -70,7 +68,7 @@ impl<'de> de::Deserializer<'de> for &mut ValueDeserializer<'de> { where V: de::Visitor<'de>, { - if let ValueCursor::Prop(cursor) = self.cursor { + if let ValueCursor::Prop(_, cursor) = self.cursor { let val = cursor.map_on(self.dtb, |data| { if data.is_empty() { true @@ -129,7 +127,7 @@ impl<'de> de::Deserializer<'de> for &mut ValueDeserializer<'de> { where V: de::Visitor<'de>, { - if let ValueCursor::Prop(cursor) = self.cursor { + if let ValueCursor::Prop(_, cursor) = self.cursor { return visitor.visit_u32(cursor.map_u32_on(self.dtb)?); } unreachable!("node -> u32"); @@ -181,7 +179,7 @@ impl<'de> de::Deserializer<'de> for &mut ValueDeserializer<'de> { where V: de::Visitor<'de>, { - if let ValueCursor::Prop(cursor) = self.cursor { + if let ValueCursor::Prop(_, cursor) = self.cursor { let data = cursor.data_on(self.dtb); return visitor.visit_borrowed_bytes(data); } @@ -200,7 +198,7 @@ impl<'de> de::Deserializer<'de> for &mut ValueDeserializer<'de> { V: de::Visitor<'de>, { match self.cursor { - ValueCursor::Prop(cursor) => { + ValueCursor::Prop(_, cursor) => { let data = cursor.data_on(self.dtb); if data.is_empty() { visitor.visit_none() @@ -242,7 +240,7 @@ impl<'de> de::Deserializer<'de> for &mut ValueDeserializer<'de> { return visitor.visit_newtype_struct(self); } match self.cursor { - ValueCursor::Prop(cursor) => match name { + ValueCursor::Prop(_, cursor) => match name { "StrSeq" => { let inner = super::str_seq::Inner { dtb: self.dtb, @@ -274,11 +272,31 @@ impl<'de> de::Deserializer<'de> for &mut ValueDeserializer<'de> { } } - fn deserialize_seq<V>(self, _visitor: V) -> Result<V::Value, Self::Error> + fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: de::Visitor<'de>, { - unreachable!("seq") + use super::{StructAccess, StructAccessType, Temp}; + match self.move_on() { + Cursor::Title(c) => { + let (name, _) = c.split_on(self.dtb); + let cursor = match self.cursor { + ValueCursor::Body(cursor) => cursor, + _ => unreachable!(""), + }; + + let pre_len = name.as_bytes().iter().take_while(|b| **b != b'@').count(); + let name_bytes = &name.as_bytes()[..pre_len]; + let name = unsafe { core::str::from_utf8_unchecked(name_bytes) }; + + visitor.visit_seq(StructAccess { + access_type: StructAccessType::Seq(name), + temp: Temp::Node(cursor, cursor), + de: self, + }) + } + _ => unreachable!("seq request on a none seq cursor"), + } } fn deserialize_tuple<V>(self, _len: usize, _visitor: V) -> Result<V::Value, Self::Error> @@ -308,7 +326,7 @@ impl<'de> de::Deserializer<'de> for &mut ValueDeserializer<'de> { if let ValueCursor::Body(cursor) = self.cursor { return visitor.visit_map(StructAccess { access_type: StructAccessType::Map(false), - temp: Temp::Node(self.body_cursor, cursor), + temp: Temp::Node(cursor, cursor), de: self, }); }; @@ -328,7 +346,7 @@ impl<'de> de::Deserializer<'de> for &mut ValueDeserializer<'de> { if let ValueCursor::Body(cursor) = self.cursor { return visitor.visit_map(StructAccess { access_type: StructAccessType::Struct(fields), - temp: Temp::Node(self.body_cursor, cursor), + temp: Temp::Node(cursor, cursor), de: self, }); }; @@ -364,7 +382,7 @@ impl<'de> de::Deserializer<'de> for &mut ValueDeserializer<'de> { impl ValueDeserializer<'_> { #[inline] - pub fn move_next(&mut self) -> super::Cursor { + pub fn move_on(&mut self) -> super::Cursor { if let ValueCursor::Body(ref mut cursor) = self.cursor { return cursor.move_on(self.dtb); }; diff --git a/src/de_mut/group.rs b/src/de_mut/group.rs deleted file mode 100644 index 4c70202..0000000 --- a/src/de_mut/group.rs +++ /dev/null @@ -1,251 +0,0 @@ -use super::{DtError, GroupCursor, RefDtb, RegConfig}; -use serde::de; - -#[allow(unused)] -#[derive(Clone, Copy)] -pub(super) struct GroupDeserializer<'de> { - pub dtb: RefDtb<'de>, - pub cursor: GroupCursor, - pub reg: RegConfig, - pub len_item: usize, - pub len_name: usize, -} - -impl<'de> de::Deserializer<'de> for &mut GroupDeserializer<'de> { - type Error = DtError; - - fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("any") - } - - fn deserialize_bool<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("bool") - } - - fn deserialize_i8<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("i8") - } - - fn deserialize_i16<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("i16") - } - - fn deserialize_i32<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("i32") - } - - fn deserialize_i64<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("i64") - } - - fn deserialize_u8<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("u8") - } - - fn deserialize_u16<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("u16") - } - - fn deserialize_u32<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("u32") - } - - fn deserialize_u64<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("u64") - } - - fn deserialize_f32<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("f32") - } - - fn deserialize_f64<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("f64") - } - - fn deserialize_char<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("char") - } - - fn deserialize_str<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("str") - } - - fn deserialize_string<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("string") - } - - fn deserialize_bytes<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("bytes") - } - - fn deserialize_byte_buf<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("byte_buf") - } - - fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - visitor.visit_some(self) - } - - fn deserialize_unit<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("unit") - } - - fn deserialize_unit_struct<V>( - self, - _name: &'static str, - _visitor: V, - ) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("unit_struct") - } - - fn deserialize_newtype_struct<V>( - self, - name: &'static str, - visitor: V, - ) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - if name == "NodeSeq" { - visitor.visit_borrowed_bytes(unsafe { - core::slice::from_raw_parts( - self as *const _ as *const u8, - core::mem::size_of::<GroupDeserializer<'_>>(), - ) - }) - } else { - visitor.visit_newtype_struct(self) - } - } - - fn deserialize_seq<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("seq") - } - - fn deserialize_tuple<V>(self, _len: usize, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("tuple") - } - - fn deserialize_tuple_struct<V>( - self, - _name: &'static str, - _len: usize, - _visitor: V, - ) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("tuple_struct") - } - - fn deserialize_map<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("map") - } - - fn deserialize_struct<V>( - self, - _name: &'static str, - _fields: &'static [&'static str], - _visitor: V, - ) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("struct") - } - - fn deserialize_enum<V>( - self, - _name: &'static str, - _variants: &'static [&'static str], - _visitor: V, - ) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("enum") - } - - fn deserialize_identifier<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("identifer") - } - - fn deserialize_ignored_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("ignored_any") - } -} diff --git a/src/de_mut/mod.rs b/src/de_mut/mod.rs index 0f9a60e..44c996e 100644 --- a/src/de_mut/mod.rs +++ b/src/de_mut/mod.rs @@ -6,7 +6,7 @@ use serde::de; mod cursor; mod data; -mod group; +// mod group; mod node; mod node_seq; mod reg; @@ -21,9 +21,8 @@ pub mod buildin { pub use super::{node::Node, node_seq::NodeSeq, reg::Reg, str_seq::StrSeq}; } -use cursor::{BodyCursor, Cursor, GroupCursor, PropCursor}; +use cursor::{BodyCursor, Cursor, PropCursor}; use data::{ValueCursor, ValueDeserializer}; -use group::GroupDeserializer; use reg::RegConfig; use structs::{RefDtb, StructureBlock, BLOCK_LEN}; @@ -40,7 +39,6 @@ where let mut d = ValueDeserializer { dtb, reg: RegConfig::DEFAULT, - body_cursor: BodyCursor::ROOT, cursor: ValueCursor::Body(BodyCursor::ROOT), }; T::deserialize(&mut d).and_then(|t| { @@ -54,14 +52,15 @@ where } // For map type, we should send root item to trans dtb and reg -enum StructAccessType { +enum StructAccessType<'de> { Map(bool), + Seq(&'de str), Struct(&'static [&'static str]), } /// 结构体解析状态。 struct StructAccess<'de, 'b> { - access_type: StructAccessType, + access_type: StructAccessType<'de>, temp: Temp, de: &'b mut ValueDeserializer<'de>, } @@ -72,7 +71,7 @@ struct StructAccess<'de, 'b> { /// 根据状态分发值解析器。 enum Temp { Node(BodyCursor, BodyCursor), - Group(GroupCursor, usize, usize), + Group(BodyCursor), Prop(BodyCursor, PropCursor), } @@ -101,7 +100,7 @@ impl<'de> de::MapAccess<'de> for StructAccess<'de, '_> { ValueCursor::Body(cursor) => cursor, _ => unreachable!("map access's cursor should always be body cursor"), }; - match self.de.move_next() { + match self.de.move_on() { // 子节点名字 Cursor::Title(c) => { let (name, _) = c.split_on(self.de.dtb); @@ -120,10 +119,10 @@ impl<'de> de::MapAccess<'de> for StructAccess<'de, '_> { else { let name_bytes = &name.as_bytes()[..pre_len]; let name = unsafe { core::str::from_utf8_unchecked(name_bytes) }; - let (group, len, next) = c.take_group_on(self.de.dtb, name); + let (group, _, next) = c.take_group_on(self.de.dtb, name); self.de.cursor = ValueCursor::Body(next); if check_contains(name) { - self.temp = Temp::Group(group, len, name.len()); + self.temp = Temp::Group(group); break name; } } @@ -167,40 +166,83 @@ impl<'de> de::MapAccess<'de> for StructAccess<'de, '_> { return seed.deserialize(&mut ValueDeserializer { dtb: self.de.dtb, reg: self.de.reg, - body_cursor: self.de.body_cursor, cursor: self.de.cursor, }); } } match self.temp { - Temp::Node(origin_cursor, cursor) => { + Temp::Node(cursor, node_cursor) => { // 键是独立节点名字,递归 - seed.deserialize(&mut ValueDeserializer { - dtb: self.de.dtb, - reg: self.de.reg, - body_cursor: origin_cursor, - cursor: ValueCursor::Body(cursor), - }) + match self.access_type { + StructAccessType::Map(_) => seed.deserialize(&mut ValueDeserializer { + dtb: self.de.dtb, + reg: self.de.reg, + cursor: ValueCursor::Body(cursor), + }), + StructAccessType::Struct(_) => seed.deserialize(&mut ValueDeserializer { + dtb: self.de.dtb, + reg: self.de.reg, + cursor: ValueCursor::Body(node_cursor), + }), + _ => unreachable!(), + } } - Temp::Group(cursor, len_item, len_name) => { + Temp::Group(cursor) => { // 键是组名字,构造组反序列化器 - seed.deserialize(&mut GroupDeserializer { + seed.deserialize(&mut ValueDeserializer { dtb: self.de.dtb, - cursor, reg: self.de.reg, - len_item, - len_name, + cursor: ValueCursor::Body(cursor), }) } Temp::Prop(origin_cursor, cursor) => { // 键是属性名字,构造属性反序列化器 seed.deserialize(&mut ValueDeserializer { dtb: self.de.dtb, - body_cursor: origin_cursor, reg: self.de.reg, - cursor: ValueCursor::Prop(cursor), + cursor: ValueCursor::Prop(origin_cursor, cursor), }) } } } } + +impl<'de> de::SeqAccess<'de> for StructAccess<'de, '_> { + type Error = DtError; + + fn next_element_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error> + where + K: de::DeserializeSeed<'de>, + { + if let StructAccessType::Seq(pre_name) = self.access_type { + match self.de.move_on() { + // 子节点名字 + Cursor::Title(c) => { + let (name, _) = c.split_on(self.de.dtb); + let (_, next) = c.take_node_on(self.de.dtb, name); + let prev_cursor = match self.de.cursor { + ValueCursor::Body(cursor) => cursor, + _ => unreachable!(), + }; + + let pre_len = name.as_bytes().iter().take_while(|b| **b != b'@').count(); + let name_bytes = &name.as_bytes()[..pre_len]; + let name = unsafe { core::str::from_utf8_unchecked(name_bytes) }; + if pre_name != name { + return Ok(None); + } + self.de.cursor = ValueCursor::Body(next); + seed.deserialize(&mut ValueDeserializer { + dtb: self.de.dtb, + reg: self.de.reg, + cursor: ValueCursor::Body(prev_cursor), + }) + .map(Some) + } + _ => Ok(None), + } + } else { + unreachable!("SeqAccess should only be accessed by seq"); + } + } +} diff --git a/src/de_mut/node.rs b/src/de_mut/node.rs index 302229a..318d62f 100644 --- a/src/de_mut/node.rs +++ b/src/de_mut/node.rs @@ -49,26 +49,20 @@ impl<'de> Node<'de> { // TODO: Maybe use BTreeMap when have alloc /// 获得节点迭代器。 pub fn nodes<'b>(&'b self) -> Option<NodeIter<'de, 'b>> { - match self.nodes_start { - None => None, - Some(node_cursor) => Some(NodeIter { + self.nodes_start.map(|node_cursor| NodeIter { node: self, cursor: node_cursor, i: 0, - }), - } + }) } /// 获得属性迭代器。 pub fn props<'b>(&'b self) -> Option<PropIter<'de, 'b>> { - match self.props_start { - None => None, - Some(node_cursor) => Some(PropIter { + self.props_start.map(|node_cursor| PropIter { node: self, cursor: node_cursor, i: 0, - }), - } + }) } } @@ -186,14 +180,14 @@ impl<'de> Deserialize<'de> for Node<'_> { continue; } match value.cursor { - ValueCursor::Prop(_) => { + ValueCursor::Prop(cursor, _) => { if props_start.is_none() { - props_start = Some(value.body_cursor); + props_start = Some(cursor); } } - ValueCursor::Body(_) => { + ValueCursor::Body(cursor) => { if nodes_start.is_none() { - nodes_start = Some(value.body_cursor); + nodes_start = Some(cursor); } } } @@ -224,7 +218,6 @@ impl<'de> NodeItem<'de> { T::deserialize(&mut ValueDeserializer { dtb: self.dtb, reg: self.reg, - body_cursor: self.node, cursor: ValueCursor::Body(self.node), }) .unwrap() @@ -261,8 +254,7 @@ impl<'de> PropItem<'de> { T::deserialize(&mut ValueDeserializer { dtb: self.dtb, reg: self.reg, - body_cursor: self.body, - cursor: ValueCursor::Prop(self.prop), + cursor: ValueCursor::Prop(self.body, self.prop), }) .unwrap() } diff --git a/src/de_mut/node_seq.rs b/src/de_mut/node_seq.rs index 824e024..3b5a7b5 100644 --- a/src/de_mut/node_seq.rs +++ b/src/de_mut/node_seq.rs @@ -1,6 +1,6 @@ -use super::{BodyCursor, GroupCursor, RefDtb, RegConfig, ValueCursor, ValueDeserializer}; -use crate::de_mut::GroupDeserializer; +use super::{BodyCursor, Cursor, RefDtb, RegConfig, ValueCursor, ValueDeserializer}; use core::{fmt::Debug, marker::PhantomData}; +use serde::de::SeqAccess; use serde::{de, Deserialize}; /// 一组名字以 `@...` 区分,同类、同级且连续的节点的映射。 @@ -9,13 +9,15 @@ use serde::{de, Deserialize}; /// 因此这些节点将延迟解析。 /// 迭代 `NodeSeq` 可获得一系列 [`NodeSeqItem`],再调用 `deserialize` 方法分别解析每个节点。 pub struct NodeSeq<'de> { - inner: GroupDeserializer<'de>, + name: &'de str, + count: usize, + starter: ValueDeserializer<'de>, } /// 连续节点迭代器。 pub struct NodeSeqIter<'de, 'b> { seq: &'b NodeSeq<'de>, - cursor: GroupCursor, + de: ValueDeserializer<'de>, i: usize, } @@ -40,28 +42,43 @@ impl<'de> Deserialize<'de> for NodeSeq<'_> { type Value = NodeSeq<'b>; fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { - write!(formatter, "struct StrSeq") + write!(formatter, "struct ValueDeserializer") } - fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E> + fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error> where - E: de::Error, + A: SeqAccess<'de>, { - // 结构体转为内存切片,然后拷贝过来 - if v.len() == core::mem::size_of::<Self::Value>() { - Ok(Self::Value::from_raw_inner_parts(v.as_ptr())) - } else { - Err(E::invalid_length( - v.len(), - &"`NodeSeq` is copied with wrong size.", - )) + let mut starter: Option<ValueDeserializer> = None; + let mut count = 0; + while let Some(node) = seq.next_element()? { + if starter.is_none() { + starter = Some(node); + } + count += 1 + } + let mut starter = starter.unwrap(); + + match starter.move_on() { + Cursor::Title(c) => { + let (name, _) = c.split_on(starter.dtb); + + let pre_len = name.as_bytes().iter().take_while(|b| **b != b'@').count(); + let name_bytes = &name.as_bytes()[..pre_len]; + let name = unsafe { core::str::from_utf8_unchecked(name_bytes) }; + Ok(NodeSeq { + name, + count, + starter, + }) + } + _ => unreachable!("NodeSeq should be inited by a node"), } } } - serde::Deserializer::deserialize_newtype_struct( + serde::Deserializer::deserialize_seq( deserializer, - "NodeSeq", Visitor { marker: PhantomData, lifetime: PhantomData, @@ -71,22 +88,9 @@ impl<'de> Deserialize<'de> for NodeSeq<'_> { } impl<'de> NodeSeq<'de> { - fn from_raw_inner_parts(ptr: *const u8) -> Self { - // 直接从指针拷贝 - let original_inner = unsafe { &*(ptr as *const GroupDeserializer<'_>) }; - let res = Self { - inner: *original_inner, - }; - // 初始化 - res.inner - .cursor - .init_on(res.inner.dtb, res.inner.len_item, res.inner.len_name); - res - } - /// 连续节点总数。 pub const fn len(&self) -> usize { - self.inner.len_item + self.count } /// 如果连续节点数量为零,返回 true。但连续节点数量不可能为零。 @@ -98,7 +102,7 @@ impl<'de> NodeSeq<'de> { pub const fn iter<'b>(&'b self) -> NodeSeqIter<'de, 'b> { NodeSeqIter { seq: self, - cursor: self.inner.cursor, + de: self.starter, i: 0, } } @@ -119,32 +123,38 @@ impl Debug for NodeSeq<'_> { } } -impl Drop for NodeSeq<'_> { - fn drop(&mut self) { - self.inner - .cursor - .drop_on(self.inner.dtb, self.inner.len_item); - } -} - impl<'de> Iterator for NodeSeqIter<'de, '_> { type Item = NodeSeqItem<'de>; fn next(&mut self) -> Option<Self::Item> { - if self.i >= self.seq.inner.len_item { + if self.i >= self.seq.len() { None } else { self.i += 1; - let dtb = self.seq.inner.dtb; - let (name, body) = self.cursor.name_on(dtb); - let off_next = self.cursor.offset_on(dtb); - self.cursor.step_n(off_next); - Some(Self::Item { - dtb, - reg: self.seq.inner.reg, - body, - at: unsafe { core::str::from_utf8_unchecked(&name[self.seq.inner.len_name + 1..]) }, - }) + match self.de.move_on() { + // 子节点名字 + Cursor::Title(c) => { + let (name, _) = c.split_on(self.de.dtb); + let (node, next) = c.take_node_on(self.de.dtb, name); + + let pre_len = name.as_bytes().iter().take_while(|b| **b != b'@').count(); + let name_bytes = &name.as_bytes()[..pre_len]; + let name = unsafe { core::str::from_utf8_unchecked(name_bytes) }; + if self.seq.name != name { + return None; + } + + self.de.cursor = ValueCursor::Body(next); + + Some(Self::Item { + dtb: self.de.dtb, + reg: self.de.reg, + body: node, + at: &name[pre_len..], + }) + } + _ => None, + } } } } @@ -162,7 +172,6 @@ impl<'de> NodeSeqItem<'de> { T::deserialize(&mut ValueDeserializer { dtb: self.dtb, reg: self.reg, - body_cursor: self.body, cursor: ValueCursor::Body(self.body), }) .unwrap() diff --git a/src/de_mut/structs.rs b/src/de_mut/structs.rs index acd9c17..88b5481 100644 --- a/src/de_mut/structs.rs +++ b/src/de_mut/structs.rs @@ -94,6 +94,7 @@ impl StructureBlock { /// 构造字节切片。 /// /// TODO + #[allow(unused)] pub fn lead_slice<'a>(&self, len: usize) -> &'a [u8] { unsafe { core::slice::from_raw_parts(self as *const _ as *const u8, len) } } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index e9e7ba3..86a0e58 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -58,7 +58,7 @@ mod tests { buildin::{Node, StrSeq}, from_raw_mut, Dtb, DtbPtr, }; - static RAW_DEVICE_TREE: &'static [u8] = + static RAW_DEVICE_TREE: &[u8] = include_bytes!("../../examples/hifive-unmatched-a00.dtb"); const BUFFER_SIZE: usize = RAW_DEVICE_TREE.len(); #[repr(align(8))] diff --git a/tests/hifive-unmatched-a00.rs b/tests/hifive-unmatched-a00.rs index eea8ef9..e01238a 100644 --- a/tests/hifive-unmatched-a00.rs +++ b/tests/hifive-unmatched-a00.rs @@ -55,5 +55,5 @@ fn hifive_unmatched() { } } assert_eq!(t.cpus.timebase_frequency, 1000000); - assert_eq!(t.cpus.u_boot_dm_spl, true); + assert!(t.cpus.u_boot_dm_spl); } From b7b58c27e0224157b8c98945bdcb2d82c5cf1cb5 Mon Sep 17 00:00:00 2001 From: Woshiluo Luo <woshiluo.luo@outlook.com> Date: Thu, 31 Oct 2024 22:22:14 +0800 Subject: [PATCH 08/10] feat: add test from qemu-virt Signed-off-by: Woshiluo Luo <woshiluo.luo@outlook.com> --- tests/qemu-virt.rs | 52 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 tests/qemu-virt.rs diff --git a/tests/qemu-virt.rs b/tests/qemu-virt.rs new file mode 100644 index 0000000..0fdc5ad --- /dev/null +++ b/tests/qemu-virt.rs @@ -0,0 +1,52 @@ +// 在实际使用中,将这里的 `serde_derive::Deserialize` 改为 `serde::Deserialize`。 +use serde_derive::Deserialize; + +use serde_device_tree::{ + buildin::{NodeSeq, Reg}, + error::Error, + from_raw_mut, Dtb, DtbPtr, +}; + +const RAW_DEVICE_TREE: &[u8] = include_bytes!("../examples/qemu-virt.dtb"); +const BUFFER_SIZE: usize = RAW_DEVICE_TREE.len(); + +#[repr(align(8))] +struct AlignedBuffer { + pub data: [u8; RAW_DEVICE_TREE.len()], +} + +#[derive(Deserialize)] +struct Tree<'a> { + soc: Soc<'a>, +} + +#[allow(dead_code)] +#[derive(Deserialize)] +struct Soc<'a> { + virtio_mmio: NodeSeq<'a>, +} + +#[derive(Deserialize)] +#[allow(unused)] +struct VirtIoMmio<'a> { + reg: Reg<'a>, +} + +#[test] +fn qemu_virt() -> Result<(), Error> { + // 整个设备树二进制文件需要装载到一块可写的内存区域 + let mut aligned_data: Box<AlignedBuffer> = Box::new(AlignedBuffer { + data: [0; BUFFER_SIZE], + }); + aligned_data.data[..BUFFER_SIZE].clone_from_slice(RAW_DEVICE_TREE); + let mut slice = aligned_data.data.to_vec(); + let ptr = DtbPtr::from_raw(slice.as_mut_ptr())?; + let dtb = Dtb::from(ptr).share(); + + let t: Tree = from_raw_mut(&dtb).unwrap(); + + assert_eq!(t.soc.virtio_mmio.len(), 8); + assert_eq!(slice, RAW_DEVICE_TREE); + + Ok(()) +} From 57e84b1d1dedccdcedc5ffa231d178f24f8a7a5e Mon Sep 17 00:00:00 2001 From: Woshiluo Luo <woshiluo.luo@outlook.com> Date: Thu, 31 Oct 2024 22:28:59 +0800 Subject: [PATCH 09/10] refactor: split StructAccess Signed-off-by: Woshiluo Luo <woshiluo.luo@outlook.com> --- src/de_mut/mod.rs | 198 +---------------------------------- src/de_mut/node.rs | 16 +-- src/de_mut/struct_access.rs | 199 ++++++++++++++++++++++++++++++++++++ src/utils/mod.rs | 3 +- 4 files changed, 210 insertions(+), 206 deletions(-) create mode 100644 src/de_mut/struct_access.rs diff --git a/src/de_mut/mod.rs b/src/de_mut/mod.rs index 44c996e..2e310a3 100644 --- a/src/de_mut/mod.rs +++ b/src/de_mut/mod.rs @@ -12,6 +12,7 @@ mod node_seq; mod reg; mod str_seq; // mod r#struct; +mod struct_access; mod structs; const VALUE_DESERIALIZER_NAME: &str = "$serde_device_tree$de_mut$ValueDeserializer"; @@ -24,6 +25,7 @@ pub mod buildin { use cursor::{BodyCursor, Cursor, PropCursor}; use data::{ValueCursor, ValueDeserializer}; use reg::RegConfig; +use struct_access::{StructAccess, StructAccessType, Temp}; use structs::{RefDtb, StructureBlock, BLOCK_LEN}; /// 从 [`RefDtb`] 反序列化一个描述设备树的 `T` 类型实例。 @@ -50,199 +52,3 @@ where } }) } - -// For map type, we should send root item to trans dtb and reg -enum StructAccessType<'de> { - Map(bool), - Seq(&'de str), - Struct(&'static [&'static str]), -} - -/// 结构体解析状态。 -struct StructAccess<'de, 'b> { - access_type: StructAccessType<'de>, - temp: Temp, - de: &'b mut ValueDeserializer<'de>, -} - -/// 用于跨键-值传递的临时变量。 -/// -/// 解析键(名字)时将确定值类型,保存 `Temp` 类型的状态。 -/// 根据状态分发值解析器。 -enum Temp { - Node(BodyCursor, BodyCursor), - Group(BodyCursor), - Prop(BodyCursor, PropCursor), -} - -impl<'de> de::MapAccess<'de> for StructAccess<'de, '_> { - type Error = DtError; - - fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error> - where - K: de::DeserializeSeed<'de>, - { - if let StructAccessType::Map(flag) = self.access_type { - if !flag { - return seed - .deserialize(de::value::BorrowedStrDeserializer::new("/")) - .map(Some); - } - } - let check_contains = |name: &str| -> bool { - match self.access_type { - StructAccessType::Struct(fields) => fields.contains(&name), - _ => true, - } - }; - let name = loop { - let origin_cursor = match self.de.cursor { - ValueCursor::Body(cursor) => cursor, - _ => unreachable!("map access's cursor should always be body cursor"), - }; - match self.de.move_on() { - // 子节点名字 - Cursor::Title(c) => { - let (name, _) = c.split_on(self.de.dtb); - - let pre_len = name.as_bytes().iter().take_while(|b| **b != b'@').count(); - // 子节点名字不带 @ 或正在解析 Node 类型 - if pre_len == name.as_bytes().len() || check_contains(name) { - let (node, next) = c.take_node_on(self.de.dtb, name); - self.de.cursor = ValueCursor::Body(next); - if check_contains(name) { - self.temp = Temp::Node(origin_cursor, node); - break name; - } - } - // @ 之前的部分是真正的名字,用这个名字搜索连续的一组 - else { - let name_bytes = &name.as_bytes()[..pre_len]; - let name = unsafe { core::str::from_utf8_unchecked(name_bytes) }; - let (group, _, next) = c.take_group_on(self.de.dtb, name); - self.de.cursor = ValueCursor::Body(next); - if check_contains(name) { - self.temp = Temp::Group(group); - break name; - } - } - } - // 属性条目 - Cursor::Prop(c) => { - let (name, next) = c.name_on(self.de.dtb); - self.de.cursor = ValueCursor::Body(next); - match name { - "#address-cells" => { - self.de.reg.address_cells = c.map_u32_on(self.de.dtb)?; - } - "#size-cells" => { - self.de.reg.size_cells = c.map_u32_on(self.de.dtb)?; - } - _ => {} - } - if check_contains(name) { - self.temp = Temp::Prop(origin_cursor, c); - break name; - } - } - // 截止符,结构体解析完成 - Cursor::End => { - self.de.step_n(1); - return Ok(None); - } - } - }; - seed.deserialize(de::value::BorrowedStrDeserializer::new(name)) - .map(Some) - } - - fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error> - where - V: de::DeserializeSeed<'de>, - { - if let StructAccessType::Map(ref mut flag) = self.access_type { - if !*flag { - *flag = true; - return seed.deserialize(&mut ValueDeserializer { - dtb: self.de.dtb, - reg: self.de.reg, - cursor: self.de.cursor, - }); - } - } - match self.temp { - Temp::Node(cursor, node_cursor) => { - // 键是独立节点名字,递归 - match self.access_type { - StructAccessType::Map(_) => seed.deserialize(&mut ValueDeserializer { - dtb: self.de.dtb, - reg: self.de.reg, - cursor: ValueCursor::Body(cursor), - }), - StructAccessType::Struct(_) => seed.deserialize(&mut ValueDeserializer { - dtb: self.de.dtb, - reg: self.de.reg, - cursor: ValueCursor::Body(node_cursor), - }), - _ => unreachable!(), - } - } - Temp::Group(cursor) => { - // 键是组名字,构造组反序列化器 - seed.deserialize(&mut ValueDeserializer { - dtb: self.de.dtb, - reg: self.de.reg, - cursor: ValueCursor::Body(cursor), - }) - } - Temp::Prop(origin_cursor, cursor) => { - // 键是属性名字,构造属性反序列化器 - seed.deserialize(&mut ValueDeserializer { - dtb: self.de.dtb, - reg: self.de.reg, - cursor: ValueCursor::Prop(origin_cursor, cursor), - }) - } - } - } -} - -impl<'de> de::SeqAccess<'de> for StructAccess<'de, '_> { - type Error = DtError; - - fn next_element_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error> - where - K: de::DeserializeSeed<'de>, - { - if let StructAccessType::Seq(pre_name) = self.access_type { - match self.de.move_on() { - // 子节点名字 - Cursor::Title(c) => { - let (name, _) = c.split_on(self.de.dtb); - let (_, next) = c.take_node_on(self.de.dtb, name); - let prev_cursor = match self.de.cursor { - ValueCursor::Body(cursor) => cursor, - _ => unreachable!(), - }; - - let pre_len = name.as_bytes().iter().take_while(|b| **b != b'@').count(); - let name_bytes = &name.as_bytes()[..pre_len]; - let name = unsafe { core::str::from_utf8_unchecked(name_bytes) }; - if pre_name != name { - return Ok(None); - } - self.de.cursor = ValueCursor::Body(next); - seed.deserialize(&mut ValueDeserializer { - dtb: self.de.dtb, - reg: self.de.reg, - cursor: ValueCursor::Body(prev_cursor), - }) - .map(Some) - } - _ => Ok(None), - } - } else { - unreachable!("SeqAccess should only be accessed by seq"); - } - } -} diff --git a/src/de_mut/node.rs b/src/de_mut/node.rs index 318d62f..25b883d 100644 --- a/src/de_mut/node.rs +++ b/src/de_mut/node.rs @@ -50,19 +50,19 @@ impl<'de> Node<'de> { /// 获得节点迭代器。 pub fn nodes<'b>(&'b self) -> Option<NodeIter<'de, 'b>> { self.nodes_start.map(|node_cursor| NodeIter { - node: self, - cursor: node_cursor, - i: 0, - }) + node: self, + cursor: node_cursor, + i: 0, + }) } /// 获得属性迭代器。 pub fn props<'b>(&'b self) -> Option<PropIter<'de, 'b>> { self.props_start.map(|node_cursor| PropIter { - node: self, - cursor: node_cursor, - i: 0, - }) + node: self, + cursor: node_cursor, + i: 0, + }) } } diff --git a/src/de_mut/struct_access.rs b/src/de_mut/struct_access.rs new file mode 100644 index 0000000..13e86ac --- /dev/null +++ b/src/de_mut/struct_access.rs @@ -0,0 +1,199 @@ +use super::{BodyCursor, Cursor, PropCursor, ValueCursor, ValueDeserializer}; +use crate::error::Error as DtError; +use serde::de; + +// For map type, we should send root item to trans dtb and reg +pub enum StructAccessType<'de> { + Map(bool), + Seq(&'de str), + Struct(&'static [&'static str]), +} + +/// 结构体解析状态。 +pub struct StructAccess<'de, 'b> { + pub access_type: StructAccessType<'de>, + pub temp: Temp, + pub de: &'b mut ValueDeserializer<'de>, +} + +/// 用于跨键-值传递的临时变量。 +/// +/// 解析键(名字)时将确定值类型,保存 `Temp` 类型的状态。 +/// 根据状态分发值解析器。 +pub enum Temp { + Node(BodyCursor, BodyCursor), + Group(BodyCursor), + Prop(BodyCursor, PropCursor), +} + +impl<'de> de::MapAccess<'de> for StructAccess<'de, '_> { + type Error = DtError; + + fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error> + where + K: de::DeserializeSeed<'de>, + { + if let StructAccessType::Map(flag) = self.access_type { + if !flag { + return seed + .deserialize(de::value::BorrowedStrDeserializer::new("/")) + .map(Some); + } + } + let check_contains = |name: &str| -> bool { + match self.access_type { + StructAccessType::Struct(fields) => fields.contains(&name), + _ => true, + } + }; + let name = loop { + let origin_cursor = match self.de.cursor { + ValueCursor::Body(cursor) => cursor, + _ => unreachable!("map access's cursor should always be body cursor"), + }; + match self.de.move_on() { + // 子节点名字 + Cursor::Title(c) => { + let (name, _) = c.split_on(self.de.dtb); + + let pre_len = name.as_bytes().iter().take_while(|b| **b != b'@').count(); + // 子节点名字不带 @ 或正在解析 Node 类型 + if pre_len == name.as_bytes().len() || check_contains(name) { + let (node, next) = c.take_node_on(self.de.dtb, name); + self.de.cursor = ValueCursor::Body(next); + if check_contains(name) { + self.temp = Temp::Node(origin_cursor, node); + break name; + } + } + // @ 之前的部分是真正的名字,用这个名字搜索连续的一组 + else { + let name_bytes = &name.as_bytes()[..pre_len]; + let name = unsafe { core::str::from_utf8_unchecked(name_bytes) }; + let (group, _, next) = c.take_group_on(self.de.dtb, name); + self.de.cursor = ValueCursor::Body(next); + if check_contains(name) { + self.temp = Temp::Group(group); + break name; + } + } + } + // 属性条目 + Cursor::Prop(c) => { + let (name, next) = c.name_on(self.de.dtb); + self.de.cursor = ValueCursor::Body(next); + match name { + "#address-cells" => { + self.de.reg.address_cells = c.map_u32_on(self.de.dtb)?; + } + "#size-cells" => { + self.de.reg.size_cells = c.map_u32_on(self.de.dtb)?; + } + _ => {} + } + if check_contains(name) { + self.temp = Temp::Prop(origin_cursor, c); + break name; + } + } + // 截止符,结构体解析完成 + Cursor::End => { + self.de.step_n(1); + return Ok(None); + } + } + }; + seed.deserialize(de::value::BorrowedStrDeserializer::new(name)) + .map(Some) + } + + fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error> + where + V: de::DeserializeSeed<'de>, + { + if let StructAccessType::Map(ref mut flag) = self.access_type { + if !*flag { + *flag = true; + return seed.deserialize(&mut ValueDeserializer { + dtb: self.de.dtb, + reg: self.de.reg, + cursor: self.de.cursor, + }); + } + } + match self.temp { + Temp::Node(cursor, node_cursor) => { + // 键是独立节点名字,递归 + match self.access_type { + StructAccessType::Map(_) => seed.deserialize(&mut ValueDeserializer { + dtb: self.de.dtb, + reg: self.de.reg, + cursor: ValueCursor::Body(cursor), + }), + StructAccessType::Struct(_) => seed.deserialize(&mut ValueDeserializer { + dtb: self.de.dtb, + reg: self.de.reg, + cursor: ValueCursor::Body(node_cursor), + }), + _ => unreachable!(), + } + } + Temp::Group(cursor) => { + // 键是组名字,构造组反序列化器 + seed.deserialize(&mut ValueDeserializer { + dtb: self.de.dtb, + reg: self.de.reg, + cursor: ValueCursor::Body(cursor), + }) + } + Temp::Prop(origin_cursor, cursor) => { + // 键是属性名字,构造属性反序列化器 + seed.deserialize(&mut ValueDeserializer { + dtb: self.de.dtb, + reg: self.de.reg, + cursor: ValueCursor::Prop(origin_cursor, cursor), + }) + } + } + } +} + +impl<'de> de::SeqAccess<'de> for StructAccess<'de, '_> { + type Error = DtError; + + fn next_element_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error> + where + K: de::DeserializeSeed<'de>, + { + if let StructAccessType::Seq(pre_name) = self.access_type { + match self.de.move_on() { + // 子节点名字 + Cursor::Title(c) => { + let (name, _) = c.split_on(self.de.dtb); + let (_, next) = c.take_node_on(self.de.dtb, name); + let prev_cursor = match self.de.cursor { + ValueCursor::Body(cursor) => cursor, + _ => unreachable!(), + }; + + let pre_len = name.as_bytes().iter().take_while(|b| **b != b'@').count(); + let name_bytes = &name.as_bytes()[..pre_len]; + let name = unsafe { core::str::from_utf8_unchecked(name_bytes) }; + if pre_name != name { + return Ok(None); + } + self.de.cursor = ValueCursor::Body(next); + seed.deserialize(&mut ValueDeserializer { + dtb: self.de.dtb, + reg: self.de.reg, + cursor: ValueCursor::Body(prev_cursor), + }) + .map(Some) + } + _ => Ok(None), + } + } else { + unreachable!("SeqAccess should only be accessed by seq"); + } + } +} diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 86a0e58..f255250 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -58,8 +58,7 @@ mod tests { buildin::{Node, StrSeq}, from_raw_mut, Dtb, DtbPtr, }; - static RAW_DEVICE_TREE: &[u8] = - include_bytes!("../../examples/hifive-unmatched-a00.dtb"); + static RAW_DEVICE_TREE: &[u8] = include_bytes!("../../examples/hifive-unmatched-a00.dtb"); const BUFFER_SIZE: usize = RAW_DEVICE_TREE.len(); #[repr(align(8))] struct AlignedBuffer { From 720a12b7e640b8f4b1b072175afe585a190756f1 Mon Sep 17 00:00:00 2001 From: Woshiluo Luo <woshiluo.luo@outlook.com> Date: Wed, 6 Nov 2024 02:03:14 +0800 Subject: [PATCH 10/10] fix: wrong at item of NodeSeqItem Signed-off-by: Woshiluo Luo <woshiluo.luo@outlook.com> --- src/de_mut/node_seq.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/de_mut/node_seq.rs b/src/de_mut/node_seq.rs index 3b5a7b5..f3d1089 100644 --- a/src/de_mut/node_seq.rs +++ b/src/de_mut/node_seq.rs @@ -134,11 +134,15 @@ impl<'de> Iterator for NodeSeqIter<'de, '_> { match self.de.move_on() { // 子节点名字 Cursor::Title(c) => { - let (name, _) = c.split_on(self.de.dtb); - let (node, next) = c.take_node_on(self.de.dtb, name); - - let pre_len = name.as_bytes().iter().take_while(|b| **b != b'@').count(); - let name_bytes = &name.as_bytes()[..pre_len]; + let (full_name, _) = c.split_on(self.de.dtb); + let (node, next) = c.take_node_on(self.de.dtb, full_name); + + let pre_len = full_name + .as_bytes() + .iter() + .take_while(|b| **b != b'@') + .count(); + let name_bytes = &full_name.as_bytes()[..pre_len]; let name = unsafe { core::str::from_utf8_unchecked(name_bytes) }; if self.seq.name != name { return None; @@ -150,7 +154,7 @@ impl<'de> Iterator for NodeSeqIter<'de, '_> { dtb: self.de.dtb, reg: self.de.reg, body: node, - at: &name[pre_len..], + at: &full_name[pre_len + 1..], }) } _ => None,