actors_rs/actor/
selection.rs1use std::iter::Peekable;
2
3use crate::actor_ref::{ActorReference, BasicActorRef};
4use crate::{
5 actor::Sender,
6 system::SystemMsg,
7 validate::{validate_path, InvalidPath},
8 Message,
9};
10
11#[derive(Debug)]
36pub struct ActorSelection {
37 anchor: BasicActorRef,
38 path_vec: Vec<Selection>,
40 path: String,
41}
42
43impl ActorSelection {
44 pub fn new(
45 anchor: BasicActorRef,
46 path: String,
48 ) -> Result<Self, InvalidPath> {
49 validate_path(&path)?;
50
51 let path_vec: Vec<Selection> = path
52 .split_terminator('/')
53 .map({
54 |seg| match seg {
55 ".." => Selection::Parent,
56 "*" => Selection::AllChildren,
57 name => Selection::ChildName(name.to_string()),
58 }
59 })
60 .collect();
61
62 Ok(Self {
63 anchor,
64 path_vec,
66 path,
67 })
68 }
69
70 pub fn try_tell<Msg>(&self, msg: Msg, sender: impl Into<Option<BasicActorRef>>)
71 where
72 Msg: Message,
73 {
74 fn walk<'a, I, Msg>(
75 anchor: &BasicActorRef,
76 mut path_vec: Peekable<I>,
78 msg: Msg,
79 sender: &Sender,
80 path: &str,
81 ) where
82 I: Iterator<Item = &'a Selection>,
83 Msg: Message,
84 {
85 let seg = path_vec.next();
86
87 match seg {
88 Some(&Selection::Parent) => {
89 if path_vec.peek().is_none() {
90 let parent = anchor.parent();
91 let _ = parent.try_tell(msg, sender.clone());
92 } else {
93 walk(&anchor.parent(), path_vec, msg, sender, path);
94 }
95 }
96 Some(&Selection::AllChildren) => {
97 for child in anchor.children() {
98 let _ = child.try_tell(msg.clone(), sender.clone());
99 }
100 }
101 Some(&Selection::ChildName(ref name)) => {
102 let child = anchor.children().filter({ |c| c.name() == name }).last();
103 if path_vec.peek().is_none() {
104 if let Some(actor_ref) = child {
105 actor_ref.try_tell(msg, sender.clone()).unwrap();
106 }
107 } else if path_vec.peek().is_some() && child.is_some() {
108 walk(
109 child.as_ref().unwrap(),
110 path_vec,
112 msg,
113 sender,
114 path,
115 );
116 } else {
117 }
119 }
120 None => {}
121 }
122 }
123
124 walk(
125 &self.anchor,
126 self.path_vec.iter().peekable(),
128 msg,
129 &sender.into(),
130 &self.path,
131 );
132 }
133
134 pub fn sys_tell(&self, msg: SystemMsg, sender: impl Into<Option<BasicActorRef>>) {
135 fn walk<'a, I>(
136 anchor: &BasicActorRef,
137 mut path_vec: Peekable<I>,
139 msg: SystemMsg,
140 sender: &Sender,
141 path: &str,
142 ) where
143 I: Iterator<Item = &'a Selection>,
144 {
145 let seg = path_vec.next();
146
147 match seg {
148 Some(&Selection::Parent) => {
149 if path_vec.peek().is_none() {
150 let parent = anchor.parent();
151 parent.sys_tell(msg);
152 } else {
153 walk(&anchor.parent(), path_vec, msg, sender, path);
154 }
155 }
156 Some(&Selection::AllChildren) => {
157 for child in anchor.children() {
158 child.sys_tell(msg.clone());
159 }
160 }
161 Some(&Selection::ChildName(ref name)) => {
162 let child = anchor.children().filter({ |c| c.name() == name }).last();
163 if path_vec.peek().is_none() {
164 if let Some(actor_ref) = child {
165 actor_ref.try_tell(msg, sender.clone()).unwrap();
166 }
167 } else if path_vec.peek().is_some() && child.is_some() {
168 walk(
169 child.as_ref().unwrap(),
170 path_vec,
172 msg,
173 sender,
174 path,
175 );
176 } else {
177 }
179 }
180 None => {}
181 }
182 }
183
184 walk(
185 &self.anchor,
186 self.path_vec.iter().peekable(),
188 msg,
189 &sender.into(),
190 &self.path,
191 );
192 }
193}
194
195#[derive(Debug)]
196enum Selection {
197 Parent,
198 ChildName(String),
199 AllChildren,
200}
201
202pub trait ActorSelectionFactory {
203 fn select(&self, path: &str) -> Result<ActorSelection, InvalidPath>;
204}