vfs/directory/watchers/event_producers.rs
1// Copyright 2019 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! When generating a watcher event, one needs "a list of names" that are then converted into
6//! buffers sent to the watchers. In a sense, an iterator over a list of strings would work, but
7//! in order to avoid copying the data around, this namespace provides a more specialized version
8//! of this abstraction.
9
10use fidl_fuchsia_io as fio;
11use static_assertions::const_assert;
12
13/// Watcher event producer, that generates buffers filled with watcher events. Watchers use this
14/// API to obtain buffers that are then sent to the actual watchers. Every producer may generate
15/// multiple events, but they all need to be of the same type, as returned by [`Self::event()`] and
16/// [`Self::mask()`] methods.
17pub trait EventProducer {
18 /// Returns a mask that represents the type of events this producer can generate, as one of the
19 /// `fidl_fuchsia_io::WatchMask::*` constants. There might be only one bit set and it should
20 /// correspond to the event returned by the [`Self::event()`] method. It is a duplication, but it
21 /// helps the callers that need both masks and event IDs.
22 fn mask(&self) -> fio::WatchMask;
23
24 /// Returns an event ID this event producer will use to populate the buffers, as one of the
25 /// `fidl_fuchsia_io::WatchEvent::*` constants. Must match what [`Self::mask()`], returns, see
26 /// there for details.
27 fn event(&self) -> fio::WatchEvent;
28
29 /// Checks if this producer can create another buffer, returning `true` if it can. This method
30 /// does not actually need to construct the buffer just yet, as an optimization if it will not
31 /// be needed.
32 fn prepare_for_next_buffer(&mut self) -> bool;
33
34 /// Returns a copy of the current buffer prepared by this producer. This method will be the
35 /// one constructing a buffer, if necessary, after a preceding call to
36 /// [`Self::prepare_for_next_buffer()`].
37 ///
38 /// Note that this method will keep returning copies of the same buffer, until
39 /// [`Self::prepare_for_next_buffer()`] is not called explicitly.
40 fn buffer(&mut self) -> Vec<u8>;
41}
42
43/// An [`EventProducer`] that uses a `Vec<String>` with names of the entires to be put into the
44/// watcher event.
45pub struct StaticVecEventProducer {
46 names: Vec<String>,
47 next: usize,
48 mask: fio::WatchMask,
49 event: fio::WatchEvent,
50 buffer: Vec<u8>,
51}
52
53impl StaticVecEventProducer {
54 /// Constructs a new [`EventProducer`] that is producing names form the specified list,
55 /// building events of type `WatchEvent::Added`. `names` is not allowed to be empty.
56 pub fn added(names: Vec<String>) -> Self {
57 Self::new(fio::WatchMask::ADDED, fio::WatchEvent::Added, names)
58 }
59
60 /// Constructs a new [`EventProducer`] that is producing names form the specified list,
61 /// building events of type `WatchEvent::Removed`. `names` is not allowed to be empty.
62 pub fn removed(names: Vec<String>) -> Self {
63 Self::new(fio::WatchMask::REMOVED, fio::WatchEvent::Removed, names)
64 }
65
66 /// Constructs a new [`EventProducer`] that is producing names form the specified list,
67 /// building events of type `WatchEvent::Existing`. `names` is not allowed to be empty.
68 pub fn existing(names: Vec<String>) -> Self {
69 Self::new(fio::WatchMask::EXISTING, fio::WatchEvent::Existing, names)
70 }
71
72 fn new(mask: fio::WatchMask, event: fio::WatchEvent, names: Vec<String>) -> Self {
73 debug_assert!(!names.is_empty());
74 Self { names, next: 0, mask, event, buffer: Vec::new() }
75 }
76}
77
78impl EventProducer for StaticVecEventProducer {
79 fn mask(&self) -> fio::WatchMask {
80 self.mask
81 }
82
83 fn event(&self) -> fio::WatchEvent {
84 self.event
85 }
86
87 fn prepare_for_next_buffer(&mut self) -> bool {
88 self.buffer.clear();
89 self.next < self.names.len()
90 }
91
92 fn buffer(&mut self) -> Vec<u8> {
93 if self.buffer.is_empty() {
94 while self.next < self.names.len() {
95 if !encode_name(&mut self.buffer, self.event, &self.names[self.next]) {
96 break;
97 }
98 self.next += 1;
99 }
100 }
101 self.buffer.clone()
102 }
103}
104
105/// An event producer for an event containing only one name.
106pub struct SingleNameEventProducer<'a> {
107 name: &'a str,
108 buffer: Vec<u8>,
109 mask: fio::WatchMask,
110 event: fio::WatchEvent,
111}
112
113impl<'a> SingleNameEventProducer<'a> {
114 /// Constructs a new [`SingleNameEventProducer`] that will produce an event for one name of
115 /// type `WatchEvent::Deleted`. Deleted refers to the directory the watcher itself is on, and
116 /// therefore statically refers to itself as ".".
117 pub fn deleted() -> Self {
118 Self::new(fio::WatchMask::DELETED, fio::WatchEvent::Deleted, ".")
119 }
120
121 /// Constructs a new [`SingleNameEventProducer`] that will produce an event for one name of
122 /// type `WatchEvent::Added`.
123 pub fn added(name: &'a str) -> Self {
124 Self::new(fio::WatchMask::ADDED, fio::WatchEvent::Added, name)
125 }
126
127 /// Constructs a new [`SingleNameEventProducer`] that will produce an event for one name of
128 /// type `WatchEvent::Removed`.
129 pub fn removed(name: &'a str) -> Self {
130 Self::new(fio::WatchMask::REMOVED, fio::WatchEvent::Removed, name)
131 }
132
133 /// Constructs a new [`SingleNameEventProducer`] that will produce an event for one name of
134 /// type `WatchEvent::Existing`.
135 pub fn existing(name: &'a str) -> Self {
136 Self::new(fio::WatchMask::EXISTING, fio::WatchEvent::Existing, name)
137 }
138
139 /// Constructs a new [`SingleNameEventProducer`] that will produce an `WatchEvent::Idle` event.
140 pub fn idle() -> Self {
141 Self::new(fio::WatchMask::IDLE, fio::WatchEvent::Idle, "")
142 }
143
144 fn new(mask: fio::WatchMask, event: fio::WatchEvent, name: &'a str) -> Self {
145 Self { name, buffer: Vec::new(), mask, event }
146 }
147}
148
149impl EventProducer for SingleNameEventProducer<'_> {
150 fn mask(&self) -> fio::WatchMask {
151 self.mask
152 }
153
154 fn event(&self) -> fio::WatchEvent {
155 self.event
156 }
157
158 fn prepare_for_next_buffer(&mut self) -> bool {
159 // The buffer is populated the first time `EventProducer::buffer` is called. If the buffer
160 // is empty then we are able to produce another buffer. If the buffer is already populated
161 // then this event has already been sent.
162 self.buffer.is_empty()
163 }
164
165 fn buffer(&mut self) -> Vec<u8> {
166 if self.buffer.is_empty() {
167 encode_name(&mut self.buffer, self.event, self.name);
168 }
169 self.buffer.clone()
170 }
171}
172
173fn encode_name(buffer: &mut Vec<u8>, event: fio::WatchEvent, name: &str) -> bool {
174 let event_size = 2 + name.len();
175 if buffer.len() + event_size > fio::MAX_BUF as usize {
176 return false;
177 }
178
179 // We are going to encode the file name length as u8.
180 const_assert!(u8::max_value() as u64 >= fio::MAX_NAME_LENGTH);
181
182 buffer.reserve(event_size);
183 buffer.push(event.into_primitive());
184 buffer.push(name.len() as u8);
185 buffer.extend_from_slice(name.as_bytes());
186 true
187}