Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
R
RoboPLC
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
黄新宇
RoboPLC
Commits
cd2d0f00
提交
cd2d0f00
authored
3月 12, 2024
作者:
Serhij S
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
derive WorkerOpts
上级
4de725fa
显示空白字符变更
内嵌
并排
正在显示
2 个修改的文件
包含
173 行增加
和
28 行删除
+173
-28
Cargo.toml
roboplc-derive/Cargo.toml
+1
-1
lib.rs
roboplc-derive/src/lib.rs
+172
-27
没有找到文件。
roboplc-derive/Cargo.toml
浏览文件 @
cd2d0f00
[package]
[package]
name
=
"roboplc-derive"
name
=
"roboplc-derive"
version
=
"0.1.
0
"
version
=
"0.1.
1
"
edition
=
"2021"
edition
=
"2021"
authors
=
[
"Serhij S. <div@altertech.com>"
]
authors
=
[
"Serhij S. <div@altertech.com>"
]
license
=
"Apache-2.0"
license
=
"Apache-2.0"
...
...
roboplc-derive/src/lib.rs
浏览文件 @
cd2d0f00
extern
crate
proc_macro
;
extern
crate
proc_macro
;
use
proc_macro
::
TokenStream
;
use
proc_macro
::
TokenStream
;
use
quote
::
quote
;
use
quote
::
quote
;
use
syn
::{
parse_macro_input
,
Data
,
DeriveInput
,
Fields
,
Meta
,
NestedMeta
};
use
syn
::{
parse_macro_input
,
Data
,
DeriveInput
,
Fields
,
Lit
,
Meta
,
MetaNameValue
,
NestedMeta
};
/// # Panics
/// # Panics
///
///
...
@@ -32,33 +32,20 @@ pub fn data_policy_derive(input: TokenStream) -> TokenStream {
...
@@ -32,33 +32,20 @@ pub fn data_policy_derive(input: TokenStream) -> TokenStream {
default_policy_impl
=
false
;
default_policy_impl
=
false
;
if
let
Meta
::
List
(
meta_list
)
=
attr
.parse_meta
()
.unwrap
()
{
if
let
Meta
::
List
(
meta_list
)
=
attr
.parse_meta
()
.unwrap
()
{
for
nested_meta
in
meta_list
.nested
{
for
nested_meta
in
meta_list
.nested
{
if
let
NestedMeta
::
Meta
(
meta
)
=
nested_meta
{
delivery_policy_value
=
match
nested_meta
{
match
meta
NestedMeta
::
Meta
(
meta
)
=>
parse_delivery_policy
(
.path
()
meta
.path
()
.get_ident
()
.get_ident
()
.map
(
ToString
::
to_string
)
.map
(|
v
|
v
.to_string
()
.to_lowercase
())
.as_deref
()
.as_deref
(),
{
),
Some
(
"single"
)
=>
{
NestedMeta
::
Lit
(
lit
)
=>
match
lit
{
delivery_policy_value
=
Lit
::
Str
(
lit_str
)
=>
parse_delivery_policy
(
Some
(
quote!
{
::
roboplc
::
DeliveryPolicy
::
Single
}
&
lit_str
.value
()
.to_lowercase
(),
}
)),
Some
(
"single_optional"
)
=>
{
_
=>
panic!
(
"data_delivery value must be a string"
),
delivery_policy_value
=
},
quote!
{
::
roboplc
::
DeliveryPolicy
::
SingleOptional
}
};
}
Some
(
"optional"
)
=>
{
delivery_policy_value
=
quote!
{
::
roboplc
::
DeliveryPolicy
::
Optional
}
}
Some
(
"always"
)
=>
{
delivery_policy_value
=
quote!
{
::
roboplc
::
DeliveryPolicy
::
Always
}
}
Some
(
v
)
=>
panic!
(
"Unknown policy variant: {}"
,
v
),
None
=>
panic!
(
"Policy variant not specified"
),
}
}
}
}
}
else
{
}
else
{
panic!
(
"unable to parse data_delivery attribute"
);
panic!
(
"unable to parse data_delivery attribute"
);
...
@@ -176,3 +163,161 @@ pub fn data_policy_derive(input: TokenStream) -> TokenStream {
...
@@ -176,3 +163,161 @@ pub fn data_policy_derive(input: TokenStream) -> TokenStream {
_
=>
panic!
(
"DataPolicy can only be derived for enums"
),
_
=>
panic!
(
"DataPolicy can only be derived for enums"
),
}
}
}
}
fn
parse_delivery_policy
(
s
:
Option
<&
str
>
)
->
proc_macro2
::
TokenStream
{
match
s
{
Some
(
"single"
)
=>
quote!
{
::
roboplc
::
DeliveryPolicy
::
Single
},
Some
(
"single_optional"
)
=>
quote!
{
::
roboplc
::
DeliveryPolicy
::
SingleOptional
},
Some
(
"optional"
)
=>
quote!
{
::
roboplc
::
DeliveryPolicy
::
Optional
},
Some
(
"always"
)
=>
quote!
{
::
roboplc
::
DeliveryPolicy
::
Always
},
Some
(
v
)
=>
panic!
(
"Unknown policy variant: {}"
,
v
),
None
=>
panic!
(
"Policy variant not specified"
),
}
}
/// # Panics
///
/// Will panic if the worker name is not specified or is invalid
#[allow(clippy
::
too_many_lines)]
#[proc_macro_derive(WorkerOpts,
attributes(worker_opts))]
pub
fn
worker_opts_derive
(
input
:
TokenStream
)
->
TokenStream
{
let
input
=
parse_macro_input!
(
input
as
DeriveInput
);
let
name
=
input
.ident
;
let
mut
worker_name
=
None
;
let
mut
stack_size
=
None
;
let
mut
scheduling
=
None
;
let
mut
priority
=
None
;
let
mut
cpus
=
Vec
::
new
();
for
attr
in
input
.attrs
{
if
attr
.path
.is_ident
(
"worker_opts"
)
{
if
let
Ok
(
Meta
::
List
(
meta_list
))
=
attr
.parse_meta
()
{
for
meta
in
&
meta_list
.nested
{
if
let
NestedMeta
::
Meta
(
Meta
::
NameValue
(
MetaNameValue
{
path
,
lit
,
..
}))
=
meta
{
if
path
.is_ident
(
"name"
)
{
if
let
Lit
::
Str
(
lit_str
)
=
lit
{
worker_name
=
Some
(
lit_str
.value
());
}
else
{
panic!
(
"worker name must be a quoted string"
);
}
}
else
if
path
.is_ident
(
"stack_size"
)
{
if
let
Lit
::
Int
(
lit_int
)
=
lit
{
stack_size
=
Some
(
lit_int
.base10_parse
::
<
usize
>
()
.unwrap
());
}
}
else
if
path
.is_ident
(
"scheduling"
)
{
scheduling
=
Some
(
parse_scheduling
(
lit
));
}
else
if
path
.is_ident
(
"priority"
)
{
if
let
Lit
::
Int
(
lit_int
)
=
lit
{
priority
=
Some
(
lit_int
.base10_parse
::
<
i32
>
()
.unwrap
());
}
}
else
if
path
.is_ident
(
"cpu"
)
{
if
let
Lit
::
Int
(
lit_int
)
=
lit
{
cpus
.push
(
lit_int
.base10_parse
::
<
usize
>
()
.unwrap
());
}
else
if
let
Lit
::
Str
(
lit_str
)
=
lit
{
let
value
=
lit_str
.value
();
if
value
.contains
(
'-'
)
{
let
bounds
:
Vec
<&
str
>
=
value
.split
(
'-'
)
.collect
();
if
bounds
.len
()
==
2
{
if
let
(
Ok
(
start
),
Ok
(
end
))
=
(
bounds
[
0
]
.parse
::
<
usize
>
(),
bounds
[
1
]
.parse
::
<
usize
>
())
{
for
cpu
in
start
..=
end
{
cpus
.push
(
cpu
);
}
}
}
}
else
if
let
Ok
(
cpu
)
=
value
.parse
::
<
usize
>
()
{
cpus
.push
(
cpu
);
}
else
{
panic!
(
"Invalid cpu value: {}"
,
value
);
}
}
}
}
}
}
}
}
let
worker_name
=
worker_name
.expect
(
"worker name is not specified"
);
assert
!
(
worker_name
.len
()
<=
15
,
"Worker name must be 15 characters or less"
);
let
stack_size_impl
=
if
let
Some
(
s
)
=
stack_size
{
quote!
{
fn
worker_stack_size
(
&
self
)
->
Option
<
usize
>
{
Some
(
#
s
)
}
}
}
else
{
quote!
{}
};
let
priority_impl
=
if
let
Some
(
p
)
=
priority
{
quote!
{
fn
worker_priority
(
&
self
)
->
Option
<
i32
>
{
Some
(
#
p
)
}
}
}
else
{
quote!
{}
};
let
cpus_impl
=
if
cpus
.is_empty
()
{
quote!
{}
}
else
{
quote!
{
fn
worker_cpu_ids
(
&
self
)
->
Option
<&
[
usize
]
>
{
Some
(
&
[
#
(
#
cpus
),
*
])
}
}
};
let
sched
=
if
let
Some
(
sched
)
=
scheduling
{
match
sched
.to_lowercase
()
.as_str
()
{
"roundrobin"
=>
Some
(
quote!
{
::
roboplc
::
thread_rt
::
Scheduling
::
RoundRobin
}),
"fifo"
=>
Some
(
quote!
{
::
roboplc
::
thread_rt
::
Scheduling
::
FIFO
}),
"idle"
=>
Some
(
quote!
{
::
roboplc
::
thread_rt
::
Scheduling
::
Idle
}),
"batch"
=>
Some
(
quote!
{
::
roboplc
::
thread_rt
::
Scheduling
::
Batch
}),
"deadline"
=>
Some
(
quote!
{
::
roboplc
::
thread_rt
::
Scheduling
::
DeadLine
}),
"normal"
=>
Some
(
quote!
{
::
roboplc
::
thread_rt
::
Scheduling
::
Normal
}),
v
=>
panic!
(
"Unknown scheduling policy: {}"
,
v
),
}
}
else
{
None
};
let
scheduling_impl
=
if
let
Some
(
s
)
=
sched
{
quote!
{
fn
worker_scheduling
(
&
self
)
->
::
roboplc
::
thread_rt
::
Scheduling
{
#
s
}
}
}
else
{
quote!
{}
};
let
expanded
=
quote!
{
impl
WorkerOptions
for
#
name
{
fn
worker_name
(
&
self
)
->
&
str
{
#
worker_name
}
#
stack_size_impl
#
scheduling_impl
#
priority_impl
#
cpus_impl
}
};
expanded
.into
()
}
fn
parse_scheduling
(
lit
:
&
Lit
)
->
String
{
match
lit
{
Lit
::
Str
(
lit_str
)
=>
lit_str
.value
(),
Lit
::
Int
(
lit_int
)
=>
lit_int
.to_string
(),
_
=>
"normal"
.to_string
(),
}
}
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论