From 0688f8c6ffe44ed045d4aedf3b8d87d3918716ae Mon Sep 17 00:00:00 2001 From: Leyman Max Date: Thu, 18 Apr 2024 23:44:26 +0300 Subject: [PATCH 1/7] Add tests for parsing --- wayland-scanner/src/parse.rs | 20 +- .../test-headerless-protocol.xml | 252 ++++++++++++++++++ 2 files changed, 271 insertions(+), 1 deletion(-) create mode 100644 wayland-scanner/tests/scanner_assets/test-headerless-protocol.xml diff --git a/wayland-scanner/src/parse.rs b/wayland-scanner/src/parse.rs index b07c6531ccf..951ffdfd159 100644 --- a/wayland-scanner/src/parse.rs +++ b/wayland-scanner/src/parse.rs @@ -27,7 +27,8 @@ macro_rules! extract_end_tag( ); pub fn parse(stream: S) -> Protocol { - let mut reader = Reader::from_reader(BufReader::new(stream)); + let buf_reader = BufReader::new(stream); + let mut reader = Reader::from_reader(buf_reader); reader.trim_text(true).expand_empty_elements(true); // Skip first event let _ = reader.read_event_into(&mut Vec::new()); @@ -366,3 +367,20 @@ fn parse_entry(reader: &mut Reader, attrs: Attributes) -> Entry { entry } + +#[cfg(test)] +mod tests { + #[test] + fn xml_parse() { + let protocol_file = + std::fs::File::open("./tests/scanner_assets/test-protocol.xml").unwrap(); + let _ = crate::parse::parse(protocol_file); + } + + #[test] + fn headerless_xml_parse() { + let protocol_file = + std::fs::File::open("./tests/scanner_assets/test-headerless-protocol.xml").unwrap(); + let _ = crate::parse::parse(protocol_file); + } +} \ No newline at end of file diff --git a/wayland-scanner/tests/scanner_assets/test-headerless-protocol.xml b/wayland-scanner/tests/scanner_assets/test-headerless-protocol.xml new file mode 100644 index 00000000000..74ec43fe7b9 --- /dev/null +++ b/wayland-scanner/tests/scanner_assets/test-headerless-protocol.xml @@ -0,0 +1,252 @@ + + + + A dummy copyright to make the parser work + + Including a few more lines. + Of text. + + + + + + + The core global object. This is a special singleton object. It + is used for internal Wayland protocol features. + + + + + The sync request asks the server to emit the 'done' event + on the returned wl_callback object. Since requests are + handled in-order and events are delivered in-order, this can + be used as a barrier to ensure all previous requests and the + resulting events have been handled. + + The object returned by this request will be destroyed by the + compositor after the callback is fired and as such the client must not + attempt to use it after that point. + + The callback_data passed in the callback is the event serial. + + + + + + + This request creates a registry object that allows the client + to list and bind the global objects available from the + compositor. + + It should be noted that the server side resources consumed in + response to a get_registry request can only be released when the + client disconnects, not when the client side proxy is destroyed. + Therefore, clients should invoke get_registry as infrequently as + possible to avoid wasting memory. + + + + + + + The error event is sent out when a fatal (non-recoverable) + error has occurred. The object_id argument is the object + where the error occurred, most often in response to a request + to that object. The code identifies the error and is defined + by the object interface. As such, each interface defines its + own set of error codes. The message is a brief description + of the error, for (debugging) convenience. + + + + + + + + + These errors are global and can be emitted in response to any + server request. + + + + + + + + + + This event is used internally by the object ID management + logic. When a client deletes an object that it had created, + the server will send this event to acknowledge that it has + seen the delete request. When the client receives this event, + it will know that it can safely reuse the object ID. + + + + + + + + The singleton global registry object. The server has a number of + global objects that are available to all clients. These objects + typically represent an actual object in the server (for example, + an input device) or they are singleton objects that provide + extension functionality. + + When a client creates a registry object, the registry object + will emit a global event for each global currently in the + registry. Globals come and go as a result of device or + monitor hotplugs, reconfiguration or other events, and the + registry will send out global and global_remove events to + keep the client up to date with the changes. To mark the end + of the initial burst of events, the client can use the + wl_display.sync request immediately after calling + wl_display.get_registry. + + A client can bind to a global object by using the bind + request. This creates a client-side handle that lets the object + emit events to the client and lets the client invoke requests on + the object. + + + + + Binds a new, client-created object to the server using the + specified name as the identifier. + + + + + + + + Notify the client of global objects. + + The event notifies the client that a global object with + the given name is now available, and it implements the + given version of the given interface. + + + + + + + + + Notify the client of removed global objects. + + This event notifies the client that the global identified + by name is no longer available. If the client bound to + the global using the bind request, the client should now + destroy that object. + + The object remains valid and requests to the object will be + ignored until the client destroys it, to avoid races between + the global going away and a client sending a request to it. + + + + + + + + Clients can handle the 'done' event to get notified when + the related request is done. + + + + + Notify the client when the related request is done. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From e3adaa280f51779a06ffc2c92a6bc0f83fb02544 Mon Sep 17 00:00:00 2001 From: Leyman Max Date: Fri, 19 Apr 2024 17:08:03 +0300 Subject: [PATCH 2/7] Fix headerless xml parsing --- wayland-scanner/src/parse.rs | 37 ++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/wayland-scanner/src/parse.rs b/wayland-scanner/src/parse.rs index 951ffdfd159..13fd2c23c16 100644 --- a/wayland-scanner/src/parse.rs +++ b/wayland-scanner/src/parse.rs @@ -27,11 +27,8 @@ macro_rules! extract_end_tag( ); pub fn parse(stream: S) -> Protocol { - let buf_reader = BufReader::new(stream); - let mut reader = Reader::from_reader(buf_reader); + let mut reader = Reader::from_reader(BufReader::new(stream)); reader.trim_text(true).expand_empty_elements(true); - // Skip first event - let _ = reader.read_event_into(&mut Vec::new()); parse_protocol(reader) } @@ -53,18 +50,30 @@ fn parse_or_panic(txt: &[u8]) -> T { } } -fn parse_protocol(mut reader: Reader) -> Protocol { - let mut protocol = extract_from!( - reader => Event::Start(bytes) => { - assert!(bytes.name().into_inner() == b"protocol", "Missing protocol toplevel tag"); - if let Some(attr) = bytes.attributes().filter_map(|res| res.ok()).find(|attr| attr.key.into_inner() == b"name") { - Protocol::new(decode_utf8_or_panic(attr.value.into_owned())) - } else { - panic!("Protocol must have a name"); - } +fn init_protocol(reader: &mut Reader) -> Protocol { + for _ in 0..2 { + println!("iter"); + match reader.read_event_into(&mut Vec::new()) { + Ok(Event::Decl(_)) => { + continue; + }, + Ok(Event::Start(bytes)) => { + assert!(bytes.name().into_inner() == b"protocol", "Missing protocol toplevel tag"); + if let Some(attr) = bytes.attributes().filter_map(|res| res.ok()).find(|attr| attr.key.into_inner() == b"name") { + return Protocol::new(decode_utf8_or_panic(attr.value.into_owned())) + } else { + panic!("Protocol must have a name"); + } + }, + _ => panic!("Ill-formed protocol file") } - ); + } + panic!("Ill-formed protocol file"); +} +fn parse_protocol(mut reader: Reader) -> Protocol { + let mut protocol = init_protocol(&mut reader); + loop { match reader.read_event_into(&mut Vec::new()) { Ok(Event::Start(bytes)) => { From 3d736ef2dd1029b45861abfd5644fbaf574d7d2d Mon Sep 17 00:00:00 2001 From: Leyman Max Date: Fri, 19 Apr 2024 17:14:11 +0300 Subject: [PATCH 3/7] Add comment --- wayland-scanner/src/parse.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wayland-scanner/src/parse.rs b/wayland-scanner/src/parse.rs index 13fd2c23c16..163e8393eb7 100644 --- a/wayland-scanner/src/parse.rs +++ b/wayland-scanner/src/parse.rs @@ -51,8 +51,8 @@ fn parse_or_panic(txt: &[u8]) -> T { } fn init_protocol(reader: &mut Reader) -> Protocol { + // Check two firsts lines for protocol tag for _ in 0..2 { - println!("iter"); match reader.read_event_into(&mut Vec::new()) { Ok(Event::Decl(_)) => { continue; From 5504fb674ab6b3312937201aa5aff06bfe49cb68 Mon Sep 17 00:00:00 2001 From: Leyman Max Date: Fri, 19 Apr 2024 17:28:14 +0300 Subject: [PATCH 4/7] Enable some protocols disabled before --- wayland-protocols-plasma/src/lib.rs | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/wayland-protocols-plasma/src/lib.rs b/wayland-protocols-plasma/src/lib.rs index 52823ec5ecc..1553f62268c 100644 --- a/wayland-protocols-plasma/src/lib.rs +++ b/wayland-protocols-plasma/src/lib.rs @@ -49,14 +49,12 @@ pub mod fake_input { ); } -// This protocol is disabled for now as the file is not valid XML because it does not have a XML header -// -// pub mod fullscreen_shell { -// wayland_protocol!( -// "./plasma-wayland-protocols/src/protocols/fullscreen-shell.xml", -// [] -// ); -// } +pub mod fullscreen_shell { + wayland_protocol!( + "./plasma-wayland-protocols/src/protocols/fullscreen-shell.xml", + [] + ); +} pub mod idle { wayland_protocol!( @@ -179,14 +177,12 @@ pub mod slide { ); } -// This protocol is disabled for now as the file is not valid XML because it does not have a XML header -// -// pub mod surface_extension { -// wayland_protocol!( -// "./plasma-wayland-protocols/src/protocols/surface-extension.xml", -// [] -// ); -// } +pub mod surface_extension { + wayland_protocol!( + "./plasma-wayland-protocols/src/protocols/surface-extension.xml", + [] + ); +} pub mod text_input { pub mod v1 { From 186eb61f99db385ef4a7c6962cfe86bec79155a4 Mon Sep 17 00:00:00 2001 From: Leyman Max Date: Fri, 19 Apr 2024 19:37:06 +0300 Subject: [PATCH 5/7] Remove useless body from tested xml file --- .../test-headerless-protocol.xml | 250 ------------------ 1 file changed, 250 deletions(-) diff --git a/wayland-scanner/tests/scanner_assets/test-headerless-protocol.xml b/wayland-scanner/tests/scanner_assets/test-headerless-protocol.xml index 74ec43fe7b9..824ebc6e32d 100644 --- a/wayland-scanner/tests/scanner_assets/test-headerless-protocol.xml +++ b/wayland-scanner/tests/scanner_assets/test-headerless-protocol.xml @@ -1,252 +1,2 @@ - - - A dummy copyright to make the parser work - - Including a few more lines. - Of text. - - - - - - - The core global object. This is a special singleton object. It - is used for internal Wayland protocol features. - - - - - The sync request asks the server to emit the 'done' event - on the returned wl_callback object. Since requests are - handled in-order and events are delivered in-order, this can - be used as a barrier to ensure all previous requests and the - resulting events have been handled. - - The object returned by this request will be destroyed by the - compositor after the callback is fired and as such the client must not - attempt to use it after that point. - - The callback_data passed in the callback is the event serial. - - - - - - - This request creates a registry object that allows the client - to list and bind the global objects available from the - compositor. - - It should be noted that the server side resources consumed in - response to a get_registry request can only be released when the - client disconnects, not when the client side proxy is destroyed. - Therefore, clients should invoke get_registry as infrequently as - possible to avoid wasting memory. - - - - - - - The error event is sent out when a fatal (non-recoverable) - error has occurred. The object_id argument is the object - where the error occurred, most often in response to a request - to that object. The code identifies the error and is defined - by the object interface. As such, each interface defines its - own set of error codes. The message is a brief description - of the error, for (debugging) convenience. - - - - - - - - - These errors are global and can be emitted in response to any - server request. - - - - - - - - - - This event is used internally by the object ID management - logic. When a client deletes an object that it had created, - the server will send this event to acknowledge that it has - seen the delete request. When the client receives this event, - it will know that it can safely reuse the object ID. - - - - - - - - The singleton global registry object. The server has a number of - global objects that are available to all clients. These objects - typically represent an actual object in the server (for example, - an input device) or they are singleton objects that provide - extension functionality. - - When a client creates a registry object, the registry object - will emit a global event for each global currently in the - registry. Globals come and go as a result of device or - monitor hotplugs, reconfiguration or other events, and the - registry will send out global and global_remove events to - keep the client up to date with the changes. To mark the end - of the initial burst of events, the client can use the - wl_display.sync request immediately after calling - wl_display.get_registry. - - A client can bind to a global object by using the bind - request. This creates a client-side handle that lets the object - emit events to the client and lets the client invoke requests on - the object. - - - - - Binds a new, client-created object to the server using the - specified name as the identifier. - - - - - - - - Notify the client of global objects. - - The event notifies the client that a global object with - the given name is now available, and it implements the - given version of the given interface. - - - - - - - - - Notify the client of removed global objects. - - This event notifies the client that the global identified - by name is no longer available. If the client bound to - the global using the bind request, the client should now - destroy that object. - - The object remains valid and requests to the object will be - ignored until the client destroys it, to avoid races between - the global going away and a client sending a request to it. - - - - - - - - Clients can handle the 'done' event to get notified when - the related request is done. - - - - - Notify the client when the related request is done. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From b7597efe2d8837c70aecc7d5eefdbd1f4b07b68c Mon Sep 17 00:00:00 2001 From: Leyman Max Date: Sat, 20 Apr 2024 12:41:40 +0300 Subject: [PATCH 6/7] Fix code formatting --- wayland-scanner/src/parse.rs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/wayland-scanner/src/parse.rs b/wayland-scanner/src/parse.rs index 163e8393eb7..73aafde625c 100644 --- a/wayland-scanner/src/parse.rs +++ b/wayland-scanner/src/parse.rs @@ -56,16 +56,20 @@ fn init_protocol(reader: &mut Reader) -> Protocol { match reader.read_event_into(&mut Vec::new()) { Ok(Event::Decl(_)) => { continue; - }, + } Ok(Event::Start(bytes)) => { assert!(bytes.name().into_inner() == b"protocol", "Missing protocol toplevel tag"); - if let Some(attr) = bytes.attributes().filter_map(|res| res.ok()).find(|attr| attr.key.into_inner() == b"name") { - return Protocol::new(decode_utf8_or_panic(attr.value.into_owned())) + if let Some(attr) = bytes + .attributes() + .filter_map(|res| res.ok()) + .find(|attr| attr.key.into_inner() == b"name") + { + return Protocol::new(decode_utf8_or_panic(attr.value.into_owned())); } else { panic!("Protocol must have a name"); } - }, - _ => panic!("Ill-formed protocol file") + } + _ => panic!("Ill-formed protocol file"), } } panic!("Ill-formed protocol file"); @@ -73,7 +77,7 @@ fn init_protocol(reader: &mut Reader) -> Protocol { fn parse_protocol(mut reader: Reader) -> Protocol { let mut protocol = init_protocol(&mut reader); - + loop { match reader.read_event_into(&mut Vec::new()) { Ok(Event::Start(bytes)) => { @@ -392,4 +396,4 @@ mod tests { std::fs::File::open("./tests/scanner_assets/test-headerless-protocol.xml").unwrap(); let _ = crate::parse::parse(protocol_file); } -} \ No newline at end of file +} From fdb758d0228e378e9cf3dac1b81192e097596e96 Mon Sep 17 00:00:00 2001 From: Leyman Max Date: Sat, 20 Apr 2024 13:01:19 +0300 Subject: [PATCH 7/7] Add changelogs --- wayland-protocols-plasma/CHANGELOG.md | 2 ++ wayland-scanner/CHANGELOG.md | 1 + 2 files changed, 3 insertions(+) diff --git a/wayland-protocols-plasma/CHANGELOG.md b/wayland-protocols-plasma/CHANGELOG.md index 8187ea5d518..b086c493c1c 100644 --- a/wayland-protocols-plasma/CHANGELOG.md +++ b/wayland-protocols-plasma/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +- Make available protocols that based on headerless xml files. + ## 0.2.0 -- 2023-09-02 ### Breaking changes diff --git a/wayland-scanner/CHANGELOG.md b/wayland-scanner/CHANGELOG.md index 1b8ea54b10d..bb378accb7f 100644 --- a/wayland-scanner/CHANGELOG.md +++ b/wayland-scanner/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased - Use wrapper type implementing `Sync` instead of `static mut`s. +- Add headerless xml file parsing possibility for `parse` function. ## 0.31.1 -- 2024-01-29