x11rb/protocol/
shm.rs

1// This file contains generated code. Do not edit directly.
2// To regenerate this, run 'make'.
3
4//! Bindings to the `Shm` X11 extension.
5
6#![allow(clippy::too_many_arguments)]
7
8#[allow(unused_imports)]
9use std::borrow::Cow;
10#[allow(unused_imports)]
11use std::convert::TryInto;
12#[allow(unused_imports)]
13use crate::utils::RawFdContainer;
14#[allow(unused_imports)]
15use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd};
16use std::io::IoSlice;
17use crate::connection::RequestConnection;
18#[allow(unused_imports)]
19use crate::connection::Connection as X11Connection;
20#[allow(unused_imports)]
21use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
22use crate::errors::ConnectionError;
23#[allow(unused_imports)]
24use crate::errors::ReplyOrIdError;
25#[allow(unused_imports)]
26use super::xproto;
27
28pub use x11rb_protocol::protocol::shm::*;
29
30/// Get the major opcode of this extension
31fn major_opcode<Conn: RequestConnection + ?Sized>(conn: &Conn) -> Result<u8, ConnectionError> {
32    let info = conn.extension_information(X11_EXTENSION_NAME)?;
33    let info = info.ok_or(ConnectionError::UnsupportedExtension)?;
34    Ok(info.major_opcode)
35}
36
37/// Query the version of the MIT-SHM extension..
38///
39/// This is used to determine the version of the MIT-SHM extension supported by the
40/// X server.  Clients MUST NOT make other requests in this extension until a reply
41/// to this requests indicates the X server supports them.
42pub fn query_version<Conn>(conn: &Conn) -> Result<Cookie<'_, Conn, QueryVersionReply>, ConnectionError>
43where
44    Conn: RequestConnection + ?Sized,
45{
46    let request0 = QueryVersionRequest;
47    let (bytes, fds) = request0.serialize(major_opcode(conn)?);
48    let slices = [IoSlice::new(&bytes[0])];
49    assert_eq!(slices.len(), bytes.len());
50    conn.send_request_with_reply(&slices, fds)
51}
52
53/// Attach a System V shared memory segment..
54///
55/// Attach a System V shared memory segment to the server.  This will fail unless
56/// the server has permission to map the segment.  The client may destroy the segment
57/// as soon as it receives a XCB_SHM_COMPLETION event with the shmseg value in this
58/// request and with the appropriate serial number.
59///
60/// # Fields
61///
62/// * `shmseg` - A shared memory segment ID created with xcb_generate_id().
63/// * `shmid` - The System V shared memory segment the server should map.
64/// * `read_only` - True if the segment shall be mapped read only by the X11 server, otherwise false.
65pub fn attach<Conn>(conn: &Conn, shmseg: Seg, shmid: u32, read_only: bool) -> Result<VoidCookie<'_, Conn>, ConnectionError>
66where
67    Conn: RequestConnection + ?Sized,
68{
69    let request0 = AttachRequest {
70        shmseg,
71        shmid,
72        read_only,
73    };
74    let (bytes, fds) = request0.serialize(major_opcode(conn)?);
75    let slices = [IoSlice::new(&bytes[0])];
76    assert_eq!(slices.len(), bytes.len());
77    conn.send_request_without_reply(&slices, fds)
78}
79
80/// Destroys the specified shared memory segment..
81///
82/// Destroys the specified shared memory segment.  This will never fail unless the
83/// segment number is incorrect.
84///
85/// # Fields
86///
87/// * `shmseg` - The segment to be destroyed.
88pub fn detach<Conn>(conn: &Conn, shmseg: Seg) -> Result<VoidCookie<'_, Conn>, ConnectionError>
89where
90    Conn: RequestConnection + ?Sized,
91{
92    let request0 = DetachRequest {
93        shmseg,
94    };
95    let (bytes, fds) = request0.serialize(major_opcode(conn)?);
96    let slices = [IoSlice::new(&bytes[0])];
97    assert_eq!(slices.len(), bytes.len());
98    conn.send_request_without_reply(&slices, fds)
99}
100
101/// Copy data from the shared memory to the specified drawable..
102///
103/// Copy data from the shared memory to the specified drawable.  The amount of bytes
104/// written to the destination image is always equal to the number of bytes read
105/// from the shared memory segment.
106///
107/// # Fields
108///
109/// * `drawable` - The drawable to draw to.
110/// * `gc` - The graphics context to use.
111/// * `total_width` - The total width of the source image.
112/// * `total_height` - The total height of the source image.
113/// * `src_x` - The source X coordinate of the sub-image to copy.
114/// * `src_y` - The source Y coordinate of the sub-image to copy.
115/// * `src_width` - The width, in source image coordinates, of the data to copy from the source.
116/// The X server will use this to determine the amount of data to copy.  The amount
117/// of the destination image that is overwritten is determined automatically.
118/// * `src_height` - The height, in source image coordinates, of the data to copy from the source.
119/// The X server will use this to determine the amount of data to copy.  The amount
120/// of the destination image that is overwritten is determined automatically.
121/// * `dst_x` - The X coordinate on the destination drawable to copy to.
122/// * `dst_y` - The Y coordinate on the destination drawable to copy to.
123/// * `depth` - The depth to use.
124/// * `format` - The format of the image being drawn.  If it is XYBitmap, depth must be 1, or a
125/// "BadMatch" error results.  The foreground pixel in the GC determines the source
126/// for the one bits in the image, and the background pixel determines the source
127/// for the zero bits.  For XYPixmap and ZPixmap, the depth must match the depth of
128/// the drawable, or a "BadMatch" error results.
129/// * `send_event` - True if the server should send an XCB_SHM_COMPLETION event when the blit
130/// completes.
131/// * `offset` - The offset that the source image starts at.
132pub fn put_image<Conn>(conn: &Conn, drawable: xproto::Drawable, gc: xproto::Gcontext, total_width: u16, total_height: u16, src_x: u16, src_y: u16, src_width: u16, src_height: u16, dst_x: i16, dst_y: i16, depth: u8, format: u8, send_event: bool, shmseg: Seg, offset: u32) -> Result<VoidCookie<'_, Conn>, ConnectionError>
133where
134    Conn: RequestConnection + ?Sized,
135{
136    let request0 = PutImageRequest {
137        drawable,
138        gc,
139        total_width,
140        total_height,
141        src_x,
142        src_y,
143        src_width,
144        src_height,
145        dst_x,
146        dst_y,
147        depth,
148        format,
149        send_event,
150        shmseg,
151        offset,
152    };
153    let (bytes, fds) = request0.serialize(major_opcode(conn)?);
154    let slices = [IoSlice::new(&bytes[0])];
155    assert_eq!(slices.len(), bytes.len());
156    conn.send_request_without_reply(&slices, fds)
157}
158
159/// Copies data from the specified drawable to the shared memory segment..
160///
161/// Copy data from the specified drawable to the shared memory segment.  The amount
162/// of bytes written to the destination image is always equal to the number of bytes
163/// read from the shared memory segment.
164///
165/// # Fields
166///
167/// * `drawable` - The drawable to copy the image out of.
168/// * `x` - The X coordinate in the drawable to begin copying at.
169/// * `y` - The Y coordinate in the drawable to begin copying at.
170/// * `width` - The width of the image to copy.
171/// * `height` - The height of the image to copy.
172/// * `plane_mask` - A mask that determines which planes are used.
173/// * `format` - The format to use for the copy (???).
174/// * `shmseg` - The destination shared memory segment.
175/// * `offset` - The offset in the shared memory segment to copy data to.
176pub fn get_image<Conn>(conn: &Conn, drawable: xproto::Drawable, x: i16, y: i16, width: u16, height: u16, plane_mask: u32, format: u8, shmseg: Seg, offset: u32) -> Result<Cookie<'_, Conn, GetImageReply>, ConnectionError>
177where
178    Conn: RequestConnection + ?Sized,
179{
180    let request0 = GetImageRequest {
181        drawable,
182        x,
183        y,
184        width,
185        height,
186        plane_mask,
187        format,
188        shmseg,
189        offset,
190    };
191    let (bytes, fds) = request0.serialize(major_opcode(conn)?);
192    let slices = [IoSlice::new(&bytes[0])];
193    assert_eq!(slices.len(), bytes.len());
194    conn.send_request_with_reply(&slices, fds)
195}
196
197/// Create a pixmap backed by shared memory..
198///
199/// Create a pixmap backed by shared memory.  Writes to the shared memory will be
200/// reflected in the contents of the pixmap, and writes to the pixmap will be
201/// reflected in the contents of the shared memory.
202///
203/// # Fields
204///
205/// * `pid` - A pixmap ID created with xcb_generate_id().
206/// * `drawable` - The drawable to create the pixmap in.
207/// * `width` - The width of the pixmap to create.  Must be nonzero, or a Value error results.
208/// * `height` - The height of the pixmap to create.  Must be nonzero, or a Value error results.
209/// * `depth` - The depth of the pixmap to create.  Must be nonzero, or a Value error results.
210/// * `shmseg` - The shared memory segment to use to create the pixmap.
211/// * `offset` - The offset in the segment to create the pixmap at.
212pub fn create_pixmap<Conn>(conn: &Conn, pid: xproto::Pixmap, drawable: xproto::Drawable, width: u16, height: u16, depth: u8, shmseg: Seg, offset: u32) -> Result<VoidCookie<'_, Conn>, ConnectionError>
213where
214    Conn: RequestConnection + ?Sized,
215{
216    let request0 = CreatePixmapRequest {
217        pid,
218        drawable,
219        width,
220        height,
221        depth,
222        shmseg,
223        offset,
224    };
225    let (bytes, fds) = request0.serialize(major_opcode(conn)?);
226    let slices = [IoSlice::new(&bytes[0])];
227    assert_eq!(slices.len(), bytes.len());
228    conn.send_request_without_reply(&slices, fds)
229}
230
231/// Create a shared memory segment.
232///
233/// Create a shared memory segment.  The file descriptor will be mapped at offset
234/// zero, and the size will be obtained using fstat().  A zero size will result in a
235/// Value error.
236///
237/// # Fields
238///
239/// * `shmseg` - A shared memory segment ID created with xcb_generate_id().
240/// * `shm_fd` - The file descriptor the server should mmap().
241/// * `read_only` - True if the segment shall be mapped read only by the X11 server, otherwise false.
242pub fn attach_fd<Conn, A>(conn: &Conn, shmseg: Seg, shm_fd: A, read_only: bool) -> Result<VoidCookie<'_, Conn>, ConnectionError>
243where
244    Conn: RequestConnection + ?Sized,
245    A: Into<RawFdContainer>,
246{
247    let shm_fd: RawFdContainer = shm_fd.into();
248    let request0 = AttachFdRequest {
249        shmseg,
250        shm_fd,
251        read_only,
252    };
253    let (bytes, fds) = request0.serialize(major_opcode(conn)?);
254    let slices = [IoSlice::new(&bytes[0])];
255    assert_eq!(slices.len(), bytes.len());
256    conn.send_request_without_reply(&slices, fds)
257}
258
259/// Asks the server to allocate a shared memory segment..
260///
261/// Asks the server to allocate a shared memory segment.  The server’s reply will
262/// include a file descriptor for the client to pass to mmap().
263///
264/// # Fields
265///
266/// * `shmseg` - A shared memory segment ID created with xcb_generate_id().
267/// * `size` - The size of the segment to create.
268/// * `read_only` - True if the server should map the segment read-only; otherwise false.
269pub fn create_segment<Conn>(conn: &Conn, shmseg: Seg, size: u32, read_only: bool) -> Result<CookieWithFds<'_, Conn, CreateSegmentReply>, ConnectionError>
270where
271    Conn: RequestConnection + ?Sized,
272{
273    let request0 = CreateSegmentRequest {
274        shmseg,
275        size,
276        read_only,
277    };
278    let (bytes, fds) = request0.serialize(major_opcode(conn)?);
279    let slices = [IoSlice::new(&bytes[0])];
280    assert_eq!(slices.len(), bytes.len());
281    conn.send_request_with_reply_with_fds(&slices, fds)
282}
283
284/// Extension trait defining the requests of this extension.
285pub trait ConnectionExt: RequestConnection {
286    /// Query the version of the MIT-SHM extension..
287    ///
288    /// This is used to determine the version of the MIT-SHM extension supported by the
289    /// X server.  Clients MUST NOT make other requests in this extension until a reply
290    /// to this requests indicates the X server supports them.
291    fn shm_query_version(&self) -> Result<Cookie<'_, Self, QueryVersionReply>, ConnectionError>
292    {
293        query_version(self)
294    }
295    /// Attach a System V shared memory segment..
296    ///
297    /// Attach a System V shared memory segment to the server.  This will fail unless
298    /// the server has permission to map the segment.  The client may destroy the segment
299    /// as soon as it receives a XCB_SHM_COMPLETION event with the shmseg value in this
300    /// request and with the appropriate serial number.
301    ///
302    /// # Fields
303    ///
304    /// * `shmseg` - A shared memory segment ID created with xcb_generate_id().
305    /// * `shmid` - The System V shared memory segment the server should map.
306    /// * `read_only` - True if the segment shall be mapped read only by the X11 server, otherwise false.
307    fn shm_attach(&self, shmseg: Seg, shmid: u32, read_only: bool) -> Result<VoidCookie<'_, Self>, ConnectionError>
308    {
309        attach(self, shmseg, shmid, read_only)
310    }
311    /// Destroys the specified shared memory segment..
312    ///
313    /// Destroys the specified shared memory segment.  This will never fail unless the
314    /// segment number is incorrect.
315    ///
316    /// # Fields
317    ///
318    /// * `shmseg` - The segment to be destroyed.
319    fn shm_detach(&self, shmseg: Seg) -> Result<VoidCookie<'_, Self>, ConnectionError>
320    {
321        detach(self, shmseg)
322    }
323    /// Copy data from the shared memory to the specified drawable..
324    ///
325    /// Copy data from the shared memory to the specified drawable.  The amount of bytes
326    /// written to the destination image is always equal to the number of bytes read
327    /// from the shared memory segment.
328    ///
329    /// # Fields
330    ///
331    /// * `drawable` - The drawable to draw to.
332    /// * `gc` - The graphics context to use.
333    /// * `total_width` - The total width of the source image.
334    /// * `total_height` - The total height of the source image.
335    /// * `src_x` - The source X coordinate of the sub-image to copy.
336    /// * `src_y` - The source Y coordinate of the sub-image to copy.
337    /// * `src_width` - The width, in source image coordinates, of the data to copy from the source.
338    /// The X server will use this to determine the amount of data to copy.  The amount
339    /// of the destination image that is overwritten is determined automatically.
340    /// * `src_height` - The height, in source image coordinates, of the data to copy from the source.
341    /// The X server will use this to determine the amount of data to copy.  The amount
342    /// of the destination image that is overwritten is determined automatically.
343    /// * `dst_x` - The X coordinate on the destination drawable to copy to.
344    /// * `dst_y` - The Y coordinate on the destination drawable to copy to.
345    /// * `depth` - The depth to use.
346    /// * `format` - The format of the image being drawn.  If it is XYBitmap, depth must be 1, or a
347    /// "BadMatch" error results.  The foreground pixel in the GC determines the source
348    /// for the one bits in the image, and the background pixel determines the source
349    /// for the zero bits.  For XYPixmap and ZPixmap, the depth must match the depth of
350    /// the drawable, or a "BadMatch" error results.
351    /// * `send_event` - True if the server should send an XCB_SHM_COMPLETION event when the blit
352    /// completes.
353    /// * `offset` - The offset that the source image starts at.
354    fn shm_put_image(&self, drawable: xproto::Drawable, gc: xproto::Gcontext, total_width: u16, total_height: u16, src_x: u16, src_y: u16, src_width: u16, src_height: u16, dst_x: i16, dst_y: i16, depth: u8, format: u8, send_event: bool, shmseg: Seg, offset: u32) -> Result<VoidCookie<'_, Self>, ConnectionError>
355    {
356        put_image(self, drawable, gc, total_width, total_height, src_x, src_y, src_width, src_height, dst_x, dst_y, depth, format, send_event, shmseg, offset)
357    }
358    /// Copies data from the specified drawable to the shared memory segment..
359    ///
360    /// Copy data from the specified drawable to the shared memory segment.  The amount
361    /// of bytes written to the destination image is always equal to the number of bytes
362    /// read from the shared memory segment.
363    ///
364    /// # Fields
365    ///
366    /// * `drawable` - The drawable to copy the image out of.
367    /// * `x` - The X coordinate in the drawable to begin copying at.
368    /// * `y` - The Y coordinate in the drawable to begin copying at.
369    /// * `width` - The width of the image to copy.
370    /// * `height` - The height of the image to copy.
371    /// * `plane_mask` - A mask that determines which planes are used.
372    /// * `format` - The format to use for the copy (???).
373    /// * `shmseg` - The destination shared memory segment.
374    /// * `offset` - The offset in the shared memory segment to copy data to.
375    fn shm_get_image(&self, drawable: xproto::Drawable, x: i16, y: i16, width: u16, height: u16, plane_mask: u32, format: u8, shmseg: Seg, offset: u32) -> Result<Cookie<'_, Self, GetImageReply>, ConnectionError>
376    {
377        get_image(self, drawable, x, y, width, height, plane_mask, format, shmseg, offset)
378    }
379    /// Create a pixmap backed by shared memory..
380    ///
381    /// Create a pixmap backed by shared memory.  Writes to the shared memory will be
382    /// reflected in the contents of the pixmap, and writes to the pixmap will be
383    /// reflected in the contents of the shared memory.
384    ///
385    /// # Fields
386    ///
387    /// * `pid` - A pixmap ID created with xcb_generate_id().
388    /// * `drawable` - The drawable to create the pixmap in.
389    /// * `width` - The width of the pixmap to create.  Must be nonzero, or a Value error results.
390    /// * `height` - The height of the pixmap to create.  Must be nonzero, or a Value error results.
391    /// * `depth` - The depth of the pixmap to create.  Must be nonzero, or a Value error results.
392    /// * `shmseg` - The shared memory segment to use to create the pixmap.
393    /// * `offset` - The offset in the segment to create the pixmap at.
394    fn shm_create_pixmap(&self, pid: xproto::Pixmap, drawable: xproto::Drawable, width: u16, height: u16, depth: u8, shmseg: Seg, offset: u32) -> Result<VoidCookie<'_, Self>, ConnectionError>
395    {
396        create_pixmap(self, pid, drawable, width, height, depth, shmseg, offset)
397    }
398    /// Create a shared memory segment.
399    ///
400    /// Create a shared memory segment.  The file descriptor will be mapped at offset
401    /// zero, and the size will be obtained using fstat().  A zero size will result in a
402    /// Value error.
403    ///
404    /// # Fields
405    ///
406    /// * `shmseg` - A shared memory segment ID created with xcb_generate_id().
407    /// * `shm_fd` - The file descriptor the server should mmap().
408    /// * `read_only` - True if the segment shall be mapped read only by the X11 server, otherwise false.
409    fn shm_attach_fd<A>(&self, shmseg: Seg, shm_fd: A, read_only: bool) -> Result<VoidCookie<'_, Self>, ConnectionError>
410    where
411        A: Into<RawFdContainer>,
412    {
413        attach_fd(self, shmseg, shm_fd, read_only)
414    }
415    /// Asks the server to allocate a shared memory segment..
416    ///
417    /// Asks the server to allocate a shared memory segment.  The server’s reply will
418    /// include a file descriptor for the client to pass to mmap().
419    ///
420    /// # Fields
421    ///
422    /// * `shmseg` - A shared memory segment ID created with xcb_generate_id().
423    /// * `size` - The size of the segment to create.
424    /// * `read_only` - True if the server should map the segment read-only; otherwise false.
425    fn shm_create_segment(&self, shmseg: Seg, size: u32, read_only: bool) -> Result<CookieWithFds<'_, Self, CreateSegmentReply>, ConnectionError>
426    {
427        create_segment(self, shmseg, size, read_only)
428    }
429}
430
431impl<C: RequestConnection + ?Sized> ConnectionExt for C {}
432
433/// A RAII-like wrapper around a [Seg].
434///
435/// Instances of this struct represent a Seg that is freed in `Drop`.
436///
437/// Any errors during `Drop` are silently ignored. Most likely an error here means that your
438/// X11 connection is broken and later requests will also fail.
439#[derive(Debug)]
440pub struct SegWrapper<C: RequestConnection>(C, Seg);
441
442impl<C: RequestConnection> SegWrapper<C>
443{
444    /// Assume ownership of the given resource and destroy it in `Drop`.
445    pub fn for_seg(conn: C, id: Seg) -> Self {
446        SegWrapper(conn, id)
447    }
448
449    /// Get the XID of the wrapped resource
450    pub fn seg(&self) -> Seg {
451        self.1
452    }
453
454    /// Assume ownership of the XID of the wrapped resource
455    ///
456    /// This function destroys this wrapper without freeing the underlying resource.
457    pub fn into_seg(self) -> Seg {
458        let id = self.1;
459        std::mem::forget(self);
460        id
461    }
462}
463
464impl<'c, C: X11Connection> SegWrapper<&'c C>
465{
466    /// Create a new Seg and return a Seg wrapper and a cookie.
467    ///
468    /// This is a thin wrapper around [attach] that allocates an id for the Seg.
469    /// This function returns the resulting `SegWrapper` that owns the created Seg and frees
470    /// it in `Drop`. This also returns a `VoidCookie` that comes from the call to
471    /// [attach].
472    ///
473    /// Errors can come from the call to [X11Connection::generate_id] or [attach].
474    pub fn attach_and_get_cookie(conn: &'c C, shmid: u32, read_only: bool) -> Result<(Self, VoidCookie<'c, C>), ReplyOrIdError>
475    {
476        let shmseg = conn.generate_id()?;
477        let cookie = attach(conn, shmseg, shmid, read_only)?;
478        Ok((Self::for_seg(conn, shmseg), cookie))
479    }
480}
481impl<C: X11Connection> SegWrapper<C>
482{
483    /// Create a new Seg and return a Seg wrapper
484    ///
485    /// This is a thin wrapper around [attach] that allocates an id for the Seg.
486    /// This function returns the resulting `SegWrapper` that owns the created Seg and frees
487    /// it in `Drop`.
488    ///
489    /// Errors can come from the call to [X11Connection::generate_id] or [attach].
490    pub fn attach(conn: C, shmid: u32, read_only: bool) -> Result<Self, ReplyOrIdError>
491    {
492        let shmseg = conn.generate_id()?;
493        let _ = attach(&conn, shmseg, shmid, read_only)?;
494        Ok(Self::for_seg(conn, shmseg))
495    }
496}
497
498impl<'c, C: X11Connection> SegWrapper<&'c C>
499{
500    /// Create a new Seg and return a Seg wrapper and a cookie.
501    ///
502    /// This is a thin wrapper around [attach_fd] that allocates an id for the Seg.
503    /// This function returns the resulting `SegWrapper` that owns the created Seg and frees
504    /// it in `Drop`. This also returns a `VoidCookie` that comes from the call to
505    /// [attach_fd].
506    ///
507    /// Errors can come from the call to [X11Connection::generate_id] or [attach_fd].
508    pub fn attach_fd_and_get_cookie<A>(conn: &'c C, shm_fd: A, read_only: bool) -> Result<(Self, VoidCookie<'c, C>), ReplyOrIdError>
509    where
510        A: Into<RawFdContainer>,
511    {
512        let shmseg = conn.generate_id()?;
513        let cookie = attach_fd(conn, shmseg, shm_fd, read_only)?;
514        Ok((Self::for_seg(conn, shmseg), cookie))
515    }
516}
517impl<C: X11Connection> SegWrapper<C>
518{
519    /// Create a new Seg and return a Seg wrapper
520    ///
521    /// This is a thin wrapper around [attach_fd] that allocates an id for the Seg.
522    /// This function returns the resulting `SegWrapper` that owns the created Seg and frees
523    /// it in `Drop`.
524    ///
525    /// Errors can come from the call to [X11Connection::generate_id] or [attach_fd].
526    pub fn attach_fd<A>(conn: C, shm_fd: A, read_only: bool) -> Result<Self, ReplyOrIdError>
527    where
528        A: Into<RawFdContainer>,
529    {
530        let shmseg = conn.generate_id()?;
531        let _ = attach_fd(&conn, shmseg, shm_fd, read_only)?;
532        Ok(Self::for_seg(conn, shmseg))
533    }
534}
535
536impl<C: RequestConnection> From<&SegWrapper<C>> for Seg {
537    fn from(from: &SegWrapper<C>) -> Self {
538        from.1
539    }
540}
541
542impl<C: RequestConnection> Drop for SegWrapper<C> {
543    fn drop(&mut self) {
544        let _ = detach(&self.0, self.1);
545    }
546}