[librsvg] load.rs: Port all of RsvgLoad to Rust. Yay!
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg] load.rs: Port all of RsvgLoad to Rust. Yay!
- Date: Tue, 11 Dec 2018 00:30:36 +0000 (UTC)
commit 018e5a677ed14a0bf216a93f3cfa2a9de92e602e
Author: Federico Mena Quintero <federico gnome org>
Date: Mon Dec 10 17:38:45 2018 -0600
load.rs: Port all of RsvgLoad to Rust. Yay!
The only remaining function in rsvg-load.[ch], rsvg_sax_error_cb(), is
in rsvg-handle.c now.
Makefile.am | 3 +-
librsvg/rsvg-handle.c | 41 +++++++++--
librsvg/rsvg-load.c | 159 ----------------------------------------
librsvg/rsvg-load.h | 40 ----------
rsvg_internals/src/lib.rs | 7 +-
rsvg_internals/src/load.rs | 158 +++++++++++++++++++++++++++++++++++++++
rsvg_internals/src/xml2.rs | 15 ----
rsvg_internals/src/xml2_load.rs | 2 +-
8 files changed, 199 insertions(+), 226 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index f1ddc052..03a5545b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -28,8 +28,6 @@ librsvg_@RSVG_API_MAJOR_VERSION@_la_SOURCES = \
librsvg/rsvg-cairo.h \
librsvg/rsvg-css.h \
librsvg/rsvg-handle.c \
- librsvg/rsvg-load.c \
- librsvg/rsvg-load.h \
librsvg/rsvg-pixbuf.c \
librsvg/rsvg-private.h \
librsvg/rsvg-size-callback.c \
@@ -88,6 +86,7 @@ RUST_SRC = \
rsvg_internals/src/iri.rs \
rsvg_internals/src/length.rs \
rsvg_internals/src/lib.rs \
+ rsvg_internals/src/load.rs \
rsvg_internals/src/log.rs \
rsvg_internals/src/link.rs \
rsvg_internals/src/marker.rs \
diff --git a/librsvg/rsvg-handle.c b/librsvg/rsvg-handle.c
index 589996f7..5f896e69 100644
--- a/librsvg/rsvg-handle.c
+++ b/librsvg/rsvg-handle.c
@@ -124,7 +124,7 @@
#include <limits.h>
#include <stdlib.h>
-#include "rsvg-load.h"
+#include <glib/gprintf.h>
#include "rsvg-private.h"
/* Implemented in rsvg_internals/src/handle.rs */
@@ -146,6 +146,13 @@ extern void rsvg_handle_rust_steal_result (RsvgHandleRust *raw_handle, RsvgXmlSt
extern void rsvg_xml_state_free (RsvgXmlState *xml);
extern gboolean rsvg_xml_state_tree_is_valid(RsvgXmlState *xml, GError **error);
+/* Implemented in rsvg_internals/src/load.rs */
+extern RsvgLoad *rsvg_load_new (RsvgXmlState *xml, gboolean unlimited_size) G_GNUC_WARN_UNUSED_RESULT;
+extern RsvgXmlState *rsvg_load_free (RsvgLoad *load) G_GNUC_WARN_UNUSED_RESULT;
+extern void rsvg_load_write (RsvgLoad *load, const guchar *buf, gsize count);
+extern gboolean rsvg_load_close (RsvgLoad *load, GError **error) G_GNUC_WARN_UNUSED_RESULT;
+
+
/* Implemented in rust/src/node.rs */
/* Call this as node = rsvg_node_unref (node); Then node will be NULL and you don't own it anymore! */
extern RsvgNode *rsvg_node_unref (RsvgNode *node);
@@ -676,10 +683,9 @@ rsvg_handle_write (RsvgHandle *handle, const guchar *buf, gsize count, GError **
priv = handle->priv;
- rsvg_return_val_if_fail (priv->hstate == RSVG_HANDLE_STATE_START
- || priv->hstate == RSVG_HANDLE_STATE_LOADING,
- FALSE,
- error);
+ g_return_val_if_fail (priv->hstate == RSVG_HANDLE_STATE_START
+ || priv->hstate == RSVG_HANDLE_STATE_LOADING,
+ FALSE);
if (priv->hstate == RSVG_HANDLE_STATE_START) {
priv->hstate = RSVG_HANDLE_STATE_LOADING;
@@ -689,7 +695,9 @@ rsvg_handle_write (RsvgHandle *handle, const guchar *buf, gsize count, GError **
g_assert (priv->hstate == RSVG_HANDLE_STATE_LOADING);
- return rsvg_load_write (priv->load, buf, count, error);
+ rsvg_load_write (priv->load, buf, count);
+
+ return TRUE;
}
static gboolean
@@ -1636,3 +1644,24 @@ rsvg_handle_internal_set_testing (RsvgHandle *handle, gboolean testing)
rsvg_handle_update_font_map_for_testing (handle);
}
+
+/* This one is defined in the C code, because the prototype has varargs
+ * and we can't handle those from Rust :(
+ */
+G_GNUC_INTERNAL void rsvg_sax_error_cb (void *data, const char *msg, ...);
+
+void
+rsvg_sax_error_cb (void *data, const char *msg, ...)
+{
+ RsvgXmlState *xml = data;
+ va_list args;
+ char *buf;
+
+ va_start (args, msg);
+ g_vasprintf (&buf, msg, args);
+ va_end (args);
+
+ rsvg_xml_state_error (xml, buf);
+
+ g_free (buf);
+}
diff --git a/rsvg_internals/src/lib.rs b/rsvg_internals/src/lib.rs
index 8e2d507b..f1fc4264 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -61,6 +61,8 @@ pub use handle::{
rsvg_handle_rust_steal_result,
};
+pub use load::{rsvg_load_close, rsvg_load_free, rsvg_load_new, rsvg_load_write};
+
pub use node::rsvg_node_unref;
pub use structure::rsvg_node_svg_get_size;
@@ -72,9 +74,7 @@ pub use xml::{
rsvg_xml_state_tree_is_valid,
};
-pub use xml2_load::{
- rsvg_xml_state_load_from_possibly_compressed_stream,
-};
+pub use xml2_load::rsvg_xml_state_load_from_possibly_compressed_stream;
#[macro_use]
mod log;
@@ -111,6 +111,7 @@ mod io;
mod iri;
mod length;
mod link;
+mod load;
mod marker;
mod mask;
mod node;
diff --git a/rsvg_internals/src/load.rs b/rsvg_internals/src/load.rs
new file mode 100644
index 00000000..69a318a4
--- /dev/null
+++ b/rsvg_internals/src/load.rs
@@ -0,0 +1,158 @@
+use gio;
+use glib::translate::*;
+use glib::{Bytes, Cast};
+use glib_sys;
+
+use std::slice;
+
+use error::set_gerror;
+use xml::XmlState;
+use xml2_load::{xml_state_load_from_possibly_compressed_stream, ParseFromStreamError};
+
+// Long-lived loading context for the deprecated I/O API
+//
+// rsvg_handle_write() and rsvg_handle_close() are old-style functions to
+// feed an RsvgHandle with data. Current code prefers the stream APIs,
+// rsvg_handle_new_from_stream_sync() and similar.
+//
+// This struct maintains the loading context while an RsvgHandle is being
+// populated with data, in case the caller is using write()/close().
+pub struct LoadContext<'a> {
+ unlimited_size: bool,
+
+ state: LoadState,
+
+ buffer: Vec<u8>,
+
+ xml: &'a mut XmlState,
+}
+
+#[derive(Copy, Clone)]
+enum LoadState {
+ Start,
+ Reading,
+ Closed,
+}
+
+impl<'a> LoadContext<'a> {
+ pub fn new(xml: &mut XmlState, unlimited_size: bool) -> LoadContext {
+ LoadContext {
+ unlimited_size,
+ state: LoadState::Start,
+ buffer: Vec::new(),
+ xml,
+ }
+ }
+
+ pub fn write(&mut self, buf: &[u8]) {
+ let state = self.state;
+
+ self.state = match state {
+ LoadState::Start => LoadState::Reading,
+ LoadState::Reading => LoadState::Reading,
+
+ _ => unreachable!(),
+ };
+
+ self.buffer.extend_from_slice(buf);
+ }
+
+ pub fn close(&mut self) -> Result<(), ParseFromStreamError> {
+ let state = self.state;
+
+ match state {
+ LoadState::Start | LoadState::Closed => {
+ self.state = LoadState::Closed;
+ Ok(())
+ }
+
+ LoadState::Reading => {
+ self.state = LoadState::Closed;
+
+ let bytes = Bytes::from(&self.buffer);
+ let stream = gio::MemoryInputStream::new_from_bytes(&bytes);
+
+ xml_state_load_from_possibly_compressed_stream(
+ &mut self.xml,
+ self.unlimited_size,
+ stream.upcast(),
+ None,
+ )
+ }
+ }
+ }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_load_new<'a>(
+ raw_xml: *mut XmlState,
+ unlimited_size: glib_sys::gboolean,
+) -> *mut LoadContext<'a> {
+ assert!(!raw_xml.is_null());
+
+ let xml = &mut *raw_xml;
+ let unlimited_size = from_glib(unlimited_size);
+
+ Box::into_raw(Box::new(LoadContext::new(xml, unlimited_size)))
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_load_free(raw_load_ctx: *mut LoadContext) -> *mut XmlState {
+ assert!(!raw_load_ctx.is_null());
+
+ let load_ctx = &mut *raw_load_ctx;
+
+ let xml = load_ctx.xml as *mut _;
+
+ Box::from_raw(raw_load_ctx);
+
+ xml
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_load_write(
+ raw_load_ctx: *mut LoadContext,
+ buf: *const u8,
+ size: usize,
+) {
+ assert!(!raw_load_ctx.is_null());
+
+ let load_ctx = &mut *raw_load_ctx;
+ let slice = slice::from_raw_parts(buf, size);
+
+ load_ctx.write(slice);
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_load_close(
+ raw_load_ctx: *mut LoadContext,
+ error: *mut *mut glib_sys::GError,
+) -> glib_sys::gboolean {
+ assert!(!raw_load_ctx.is_null());
+
+ let load_ctx = &mut *raw_load_ctx;
+
+ match load_ctx.close() {
+ Ok(()) => true.to_glib(),
+
+ Err(e) => {
+ match e {
+ ParseFromStreamError::CouldNotCreateParser => {
+ set_gerror(error, 0, "Error creating XML parser");
+ }
+
+ ParseFromStreamError::IoError(e) => {
+ if !error.is_null() {
+ *error = e.to_glib_full() as *mut _;
+ }
+ }
+
+ ParseFromStreamError::XmlParseError(s) => {
+ set_gerror(error, 0, &s);
+ }
+ }
+
+ false.to_glib()
+ }
+ }
+}
diff --git a/rsvg_internals/src/xml2.rs b/rsvg_internals/src/xml2.rs
index 25d2e058..4525fc4b 100644
--- a/rsvg_internals/src/xml2.rs
+++ b/rsvg_internals/src/xml2.rs
@@ -163,14 +163,6 @@ pub type xmlInputCloseCallback = Option<unsafe extern "C" fn(
pub type xmlCharEncoding = libc::c_int;
extern "C" {
- pub fn xmlCreatePushParserCtxt(
- sax: xmlSAXHandlerPtr,
- user_data: *mut libc::c_void,
- chunk: *const libc::c_char,
- size: libc::c_int,
- filename: *const libc::c_char,
- ) -> xmlParserCtxtPtr;
-
pub fn xmlCreateIOParserCtxt(
sax: xmlSAXHandlerPtr,
user_data: *mut libc::c_void,
@@ -180,13 +172,6 @@ extern "C" {
enc: xmlCharEncoding,
) -> xmlParserCtxtPtr;
- pub fn xmlParseChunk(
- ctxt: xmlParserCtxtPtr,
- chunk: *const libc::c_char,
- size: libc::c_int,
- terminate: libc::c_int,
- ) -> libc::c_int;
-
pub fn xmlParseDocument(ctxt: xmlParserCtxtPtr) -> libc::c_int;
pub fn xmlFreeDoc(doc: xmlDocPtr);
diff --git a/rsvg_internals/src/xml2_load.rs b/rsvg_internals/src/xml2_load.rs
index 9cf822fb..63eb61a0 100644
--- a/rsvg_internals/src/xml2_load.rs
+++ b/rsvg_internals/src/xml2_load.rs
@@ -410,7 +410,7 @@ pub fn xml_state_parse_from_stream(
.and_then(|parser| parser.parse())
}
-fn xml_state_load_from_possibly_compressed_stream(
+pub fn xml_state_load_from_possibly_compressed_stream(
xml: &mut XmlState,
unlimited_size: bool,
stream: gio::InputStream,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]