21次发布

0.10.3 2024年2月6日
0.9.2 2023年7月4日
0.7.2 2023年3月29日
0.2.0 2022年11月19日

#39 in 配置

Download history 71/week @ 2024-03-07 473/week @ 2024-03-14 6/week @ 2024-03-28 1/week @ 2024-04-04

137 每月下载量

MPL-2.0 许可证

705KB
16K SLoC

shm-rs

一个Rust包,允许动态配置和读取基于方案的配置文件,并将数据序列化为JSON或二进制文件,以便稍后可以直接反序列化为结构体。

此包还能从静态方案文件构造Rust结构体和枚举。

静态方案文件 是一个包含以下描述的文件:

  • 如何读取用户提供的配置文件
  • 如何存储收集的数据
  • 如何序列化它(顺序)

动态方案文件 是一个包含读取和序列化所需配置的文件。

特性

  • 序列化或反序列化
  • 数据结构和集合
  • 结构/枚举回到方案(可读格式)

有关语法,请参阅 /docs/。

版本日志

V0.10.2
- Fixed generaion of code structure, added std::ops to Range and RangeInclusive.
- Cleaned old changelog.
- Moving towards the release V1.0.0

V0.10.(0-1)
- Added a multiline comment section ;[your comment here];
- Reimplemented error reporting for dynamic scheme.
- Added a config loader, collector

V0.9.2
Fixed problem with deserialization to scheme of lognint and longuint. (Patch had not applied correctly and the maintainer did not noticed it).

V 0.9.1 erased.

V0.9.1
Fixed problem with longint and longuint serialization and translation problem.

V 0.9.0 erased.

V0.9
Removed generics from the Lexer. Now default int, uint types are i64 and u64 which 
should be deserialized into equal sized or lower types.
The default long int and long uint are i128 and u128.
This was specially made to bind the data types to avoid any sort of incompatability.
Most of the systems are 64bits and I don't think that there is a need in 32bit mode.

V0.8.4
Fixed issue with arg-enums. 
Added static check which tests if enum item has same identifier name as define.

V0.8.3
Fixed problem with escape charater when converting back to the schema from structures.
Added list of escape sequences in Lexer.

V0.8.2
Fixed misprint title of the function in RustCode.
Fixed problem when argenum options were ordered in arbitrary order. An IndexSet
is now used which should store items in hashset in sequence.

V0.8.1
Fixed error missing enum bind name for f/argenum in f/vector.

V0.8
Added functions to lib.rs

Added:
(arg-enum-bind)

版本编号

直到V1.0.0,此库完全是实验性的,其代码和语法可能发生重大变化。

次要版本号表示配置文件语法或包代码的变化。

构建号是错误修复。不应进行代码更改。

序列

┌───────────────────┐              ┌───────────────────────┐
│ static_scheme.shm │              │  dynamic_scheme.shm   ◄─────────────┐
└────────┬──────────┘              └──────────┬────────────┘             │
         │                                    │                          │
         │                                    │                          │
         │                                    │                          │
 ┌───────▼─────────┐                 ┌────────▼─────────┐                │
 │  File / Buffer  │                 │  File / Buffer   │                │
 └───────┬─────────┘                 └────────┬─────────┘                │
         │                                    │                          │
         │ text                               │ text                     │
         │                                    │                          │
 ┌───────▼─────────┐                  ┌───────▼─────────┐                │
 │     Lexer       │                  │     Lexer       │                │
 └───────┬─────────┘                  └───────┬─────────┘                │
         │                                    │                          │
         │                                    │   data                   │
         │                                    │                          │
 ┌───────▼─────────┐                  ┌───────▼──────────┐               │
 │                 │      structure   │                  │               │
 │  StaticScheme   ├──────────┬───────►  DynamicScheme   │               │
 │                 │          │       │                  │               │
 └───────┬─────────┘          │       └───────┬──────────┘               │
         │  STRUCTURED DESCR  │               │                          │
         │                    │               │ Collected from scheme    │
         │                    │               │                          │
   ┌─────▼──────┐             │       ┌───────▼──────────┐               │
   │  RustCode  │             │       │ Structured Data  │               │
   └─────┬──────┘             │       └───────┬──────────┘               │
         │                    │               │                          │
         │                    │               │                          │
    ┌────▼──────┐             │       ┌───────▼──────────┐               │
    │Generated  │             └───────►  Serializator    │               │
    │Rust Code  │                     └───────┬──────────┘               │
    │Structures │                             │                          │
    │Enums      │                             │                          │
    │Consts     │                     ┌───────▼──────────┐               │
    └────┬──────┘                     │  Serialized Data │               │
         │                            │                  │               │
         │structure                   │  Binary/JSON     │               │
         │                            └──┬───────────────┘               │
         │                               │                               │
         │                               │                               │
     ┌───▼───────────────┐    data       │                               │
     │ Serde Deserialize ◄───────────────┘                               │
     └────────┬──────────┘                                               │
              │                                                          │
              │       data+structs  ┌──────────────────┐                 │
              │          ┌──────────► Serde Serialize  │                 │
              │          │          └───────┬──────────┘                 │
              │          │                  │                            │
     ┌────────▼──────────┤       ┌──────────▼──────────┐                 │
     │  Structures       │       │    Composer         ├─────────────────┘
     │  Enums            │       │    Struct2scheme    │
     └───────────────────┘       └─────────────────────┘

示例

动态方案文件(即 DynamicScheme)的示例

(machine
    (address "01:40/5010-A3F.0") ; router's address (to access admin panel)
    (address "01:40/5010-A40.0") ; another adress (to access admin panel)
)

;; A 100MBit interface uplink from <another company> 
;; Clients from floor 2 using only this connection
(interface "wan0" 
    (phys-location "00:00:01")
    (address "01:40/5010-A3F")
    (mtu 2048u) ; 2 kiB
    (address-mask "01:40/5010-(A3F-A4A)")
)

;; A 1Gbit interface uplink from <title>
(interface "wwan1"
    (phys-location "00:00:02")
    (address "01:40/5010-A3F")
    (mtu 2048u)
    (address-mask "01:40/5010-(A3F-A4A)")
)

;; All client machines connected to router (floor 1)
(interface "lan0"
    (phys-location "00:01:01")
    (address "01:40/5010-A3F")
    (mtu 2048u)
    (address-mask "01:40/5010-A3F.(0-FFFF)")
)

;; All client machines connected to router (floor 2)
(interface "lan1"
    (phys-location "00:01:02")
    (address "01:40/5010-A40")
    (mtu 2048u)
    (address-mask "01:40/5010-A40.(0-FFFF)")
)

;; Route announcement
;; Clients on lan0 would receive:
;; to: 01:40/5010-(A3F-A40) metric: 1
;; to: 01:40/5010-any metric 1
;; to: any metric 1
(route-table "global"
    (interface-alias "lan0" ; announce the following routes on interface lan0
        (route-to "01:40/5010-(A3F-A40).*"
            (metric 1u)
        )
        (route-to "01:40/5010-*" 
            (via "wan0")
            (metric auto)
        )
        ; routing globally to whole internet
        (route-to "*" 
            (via "wwan1")
            (metric auto)
        )
    )

    (interface-alias "lan1"
        (route-to "01:40/5010-(A3F-A40).*"
            (metric 1u)
        )
        (route-to "*" 
            (via "wan0")
            (metric auto)
        )
        ; do not route to global internet via wwan1
    )

    ;; inbound routing
    ;; announce to uplink that we have something on our network
    ;; if there are any machines that is local only then don't announce the 
    ;; adress to uplink, so no route to host would be returned by uplink for the
    ;; remote host.
    (interface-alias "wan0"
        (route-to "01:40/5010-A3F.*" 
            (via "lan0")
            (metric 1u)
        )

        (route-to "01:40/5010-A40.*"
            (via "lan1")
            (metric 1u)
        )
    )

    (interface-alias "wwan1"
        (route-to "01:40/5010-A3F.*" 
            (via "lan0")
            (metric 1u)
        )

        ; no route to lan1 members via this interface
    )
)

为此,需要以下静态方案 StaticScheme 以便读取和序列化

(version 1000)

(serializator "networking"
    (define "auto" 0u '("metric"))

    (procedure "address"
        (arg "a_addr" string)
    )

    ;(struct "NetAddr" "address"
    ;    (field "net_addr" (f/string '("a_addr")))
    ;)

    ; -- MACHINE
    (procedure "machine"
        (proc "p_address" '("address") (proc-allow '(collection)))
    )

    (struct "NetMachine" "machine"
        ;(field "nm_addrs" (f/vector (f/struct '("p_address"))))
        (field "nm_addrs" (f/vector (f/string '("p_address" "a_addr"))))
    )

    ; -- COMMON
    (procedure "phys-location"
        (arg "a_phys_loc" string)
    )

    (procedure "mtu"
        (arg "a_mtu" uint)
    )

    (procedure "address-mask"
        (arg "a_addr_mask" string)
    )

    ; -- INTERFACE

    (procedure "interface"
        (arg "a_if_alias" string)
        (proc "p_phys_loc" '("phys-location"))
        (proc "p_addr" '("address"))
        (proc "p_mtu" '("mtu") (proc-allow '(optional)))
        (proc "p_address_mask" '("address-mask"))
    )

    (struct "NetInterface" "interface"
        (field "ni_ifalias" (f/string '("a_if_alias")))
        (field "ni_ifloc" (f/string '("p_phys_loc" "a_phys_loc")))
        (field "ni_addr" (f/string '("p_addr" "a_addr")))
        (field "ni_ifmtu" (f/optional) (f/uint '("p_mtu" "a_mtu")))
        (field "ni_ifaddr_mask" (f/string '("p_address_mask" "a_addr_mask")))
    )

    ; -- ROUTE-TABLE

    (procedure "via"
        (arg "a_via" string)
    )

    (procedure "metric" 
        (arg "a_metric" symbol uint)
    )

    (procedure "route-to"
        (arg "a_route_addr" string)
        (proc "p_via" '("via") (proc-allow '(optional)))
        (proc "p_metric" '("metric"))
    )

    (struct "NetRouteTo" "route-to"
        (field "rt_dest" (f/string '("a_route_addr")))
        (field "rt_via" (f/optional) (f/string '("p_via" "a_via")))
        (field "rt_metric" (f/uint '("p_metric" "a_metric")))
    )

    (procedure "interface-alias"
        (arg "a_route_title" string)
        (proc "p_route_to" '("route-to") (proc-allow '(collection)))
    )

    (struct "NetInterfaceAlias" "interface-alias"
        (field "if_alias" (f/string '("a_route_title")))
        (field "if_routes_to" (f/vector (f/struct '("p_route_to"))))
    )

    (procedure "route-table"
        (arg "a_route_title" string)
        (proc "p_route_tables" '("interface-alias") (proc-allow '(collection optional)))
    )

    (struct "NetRouteTable" "route-table"
        (field "rt_title" (f/string '("a_route_title")))
        (field "rt_tbls" (f/optional) (f/vector (f/struct '("p_route_tables"))))
    )

    ; -- ROOT

    (rootprocedure
        (proc "p_machine" '("machine"))
        (proc "p_interface" '("interface") (proc-allow '(collection)))
        (proc "p_route_tables" '("route-table") (proc-allow '(collection)))
    )

    (rootstruct "Network"
        (field "net_machine" (f/struct '("p_machine")))
        (field "net_ifs" (f/vector (f/struct '("p_interface"))))
        (field "net_rt_tbls" (f/vector (f/struct '("p_route_tables"))))
    )
)

因此,上述配置将序列化为

{
  "net_machine": {
    "nm_addrs": [
      "01:40/5010-A3F.0",
      "01:40/5010-A40.0"
    ]
  },
  "net_ifs": [
    {
      "ni_ifalias": "wan0",
      "ni_ifloc": "00:00:01",
      "ni_addr": "01:40/5010-A3F",
      "ni_ifmtu": 2048,
      "ni_ifaddr_mask": "01:40/5010-(A3F-A4A)"
    },
    {
      "ni_ifalias": "wwan1",
      "ni_ifloc": "00:00:02",
      "ni_addr": "01:40/5010-A3F",
      "ni_ifmtu": 2048,
      "ni_ifaddr_mask": "01:40/5010-(A3F-A4A)"
    },
    {
      "ni_ifalias": "lan0",
      "ni_ifloc": "00:01:01",
      "ni_addr": "01:40/5010-A3F",
      "ni_ifmtu": 2048,
      "ni_ifaddr_mask": "01:40/5010-A3F.(0-FFFF)"
    },
    {
      "ni_ifalias": "lan1",
      "ni_ifloc": "00:01:02",
      "ni_addr": "01:40/5010-A40",
      "ni_ifmtu": 2048,
      "ni_ifaddr_mask": "01:40/5010-A40.(0-FFFF)"
    }
  ],
  "net_rt_tbls": [
    {
      "rt_title": "global",
      "rt_tbls": [
        {
          "if_alias": "lan0",
          "if_routes_to": [
            {
              "rt_dest": "01:40/5010-(A3F-A40).*",
              "rt_via": null,
              "rt_metric": 1
            },
            {
              "rt_dest": "01:40/5010-*",
              "rt_via": "wan0",
              "rt_metric": 0
            },
            {
              "rt_dest": "*",
              "rt_via": "wwan1",
              "rt_metric": 0
            }
          ]
        },
        {
          "if_alias": "lan1",
          "if_routes_to": [
            {
              "rt_dest": "01:40/5010-(A3F-A40).*",
              "rt_via": null,
              "rt_metric": 1
            },
            {
              "rt_dest": "*",
              "rt_via": "wan0",
              "rt_metric": 0
            }
          ]
        },
        {
          "if_alias": "wan0",
          "if_routes_to": [
            {
              "rt_dest": "01:40/5010-A3F.*",
              "rt_via": "lan0",
              "rt_metric": 1
            },
            {
              "rt_dest": "01:40/5010-A40.*",
              "rt_via": "lan1",
              "rt_metric": 1
            }
          ]
        },
        {
          "if_alias": "wwan1",
          "if_routes_to": [
            {
              "rt_dest": "01:40/5010-A3F.*",
              "rt_via": "lan0",
              "rt_metric": 1
            }
          ]
        }
      ]
    }
  ]
}

未经格式化的原始结果

{"net_machine":{"nm_addrs":["01:40/5010-A3F.0","01:40/5010-A40.0"]},"net_ifs":[{"ni_ifalias":"wan0","ni_ifloc":"00:00:01","ni_addr":"01:40/5010-A3F","ni_ifmtu":2048,"ni_ifaddr_mask":"01:40/5010-(A3F-A4A)"},{"ni_ifalias":"wwan1","ni_ifloc":"00:00:02","ni_addr":"01:40/5010-A3F","ni_ifmtu":2048,"ni_ifaddr_mask":"01:40/5010-(A3F-A4A)"},{"ni_ifalias":"lan0","ni_ifloc":"00:01:01","ni_addr":"01:40/5010-A3F","ni_ifmtu":2048,"ni_ifaddr_mask":"01:40/5010-A3F.(0-FFFF)"},{"ni_ifalias":"lan1","ni_ifloc":"00:01:02","ni_addr":"01:40/5010-A40","ni_ifmtu":2048,"ni_ifaddr_mask":"01:40/5010-A40.(0-FFFF)"}],"net_rt_tbls":[{"rt_title":"global","rt_tbls":[{"if_alias":"lan0","if_routes_to":[{"rt_dest":"01:40/5010-(A3F-A40).*","rt_via":null,"rt_metric":1},{"rt_dest":"01:40/5010-*","rt_via":"wan0","rt_metric":0},{"rt_dest":"*","rt_via":"wwan1","rt_metric":0}]},{"if_alias":"lan1","if_routes_to":[{"rt_dest":"01:40/5010-(A3F-A40).*","rt_via":null,"rt_metric":1},{"rt_dest":"*","rt_via":"wan0","rt_metric":0}]},{"if_alias":"wan0","if_routes_to":[{"rt_dest":"01:40/5010-A3F.*","rt_via":"lan0","rt_metric":1},{"rt_dest":"01:40/5010-A40.*","rt_via":"lan1","rt_metric":1}]},{"if_alias":"wwan1","if_routes_to":[{"rt_dest":"01:40/5010-A3F.*","rt_via":"lan0","rt_metric":1}]}]}]}

以下Rust代码将使用 generator.rs 生成

use serde::{Serialize, Deserialize};

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct NetMachine 
{ 
    pub nm_addrs: Vec<String>
}


#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct NetInterface 
{ 
    pub ni_ifalias: String,
    pub ni_ifloc: String,
    pub ni_addr: String,
    pub ni_ifmtu: Option<u64>,
    pub ni_ifaddr_mask: String
}


#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct NetRouteTo 
{ 
    pub rt_dest: String,
    pub rt_via: Option<String>,
    pub rt_metric: u64
}


#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct NetInterfaceAlias 
{ 
    pub if_alias: String,
    pub if_routes_to: Vec<NetRouteTo>
}


#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct NetRouteTable 
{ 
    pub rt_title: String,
    pub rt_tbls: Option<Vec<NetInterfaceAlias>>
}


#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Network 
{ 
    pub net_machine: NetMachine,
    pub net_ifs: Vec<NetInterface>,
    pub net_rt_tbls: Vec<NetRouteTable>
}

依赖项

~1.7–2.7MB
~56K SLoC