[build-path-prefix-map-spec] 24/50: Example code in Rust (unfinished, needs Windows-specific code)

Ximin Luo infinity0 at debian.org
Fri Mar 10 15:17:20 UTC 2017


This is an automated email from the git hooks/post-receive script.

infinity0 pushed a commit to branch master
in repository build-path-prefix-map-spec.

commit 2242fb725583049ea9e6ea13dd1ea64930a284b1
Author: Ximin Luo <infinity0 at debian.org>
Date:   Tue Jan 31 21:07:16 2017 +0100

    Example code in Rust (unfinished, needs Windows-specific code)
---
 consume/Makefile    | 10 +++++--
 consume/pecsplit.rs | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 93 insertions(+), 2 deletions(-)

diff --git a/consume/Makefile b/consume/Makefile
index 1e44b01..4d5ec71 100644
--- a/consume/Makefile
+++ b/consume/Makefile
@@ -6,13 +6,16 @@ TMPDIR = /run/shm/rb-prefix-map
 T = testcases/
 
 ALL_FORMATS = pecsplit
-ALL_SOURCE = pecsplit.c
-ALLCHECK_pecsplit = pecsplit.c.out pecsplit.js pecsplit.py
+ALL_SOURCE = pecsplit.c pecsplit.rs
+ALLCHECK_pecsplit = pecsplit.c.out pecsplit.rs.out pecsplit.js pecsplit.py
 
 export AFL_USE_ASAN=1
 AFL_MEMLIM = none
 # 20971595M also seems to work with afl-gcc amd64 6.2.1-5
 
+CC ?= cc
+RUSTC ?= rustc
+
 find_testcases = \
 	TESTCASES_$(1) = $(patsubst $(T)$(1).%.in,$(1).%,$(wildcard $(T)$(1).*.in))
 $(eval $(call find_testcases,0))
@@ -26,6 +29,9 @@ all: $(ALL_SOURCE:%=%.out)
 %.c.out: %.c prefix_map.h
 	$(CC) -Wall -o "$@" "$<"
 
+%.rs.out: %.rs
+	$(RUSTC) -W warnings -o "$@" "$<"
+
 .PHONY: check
 check: $(ALL_FORMATS:%=check-%)
 
diff --git a/consume/pecsplit.rs b/consume/pecsplit.rs
new file mode 100644
index 0000000..b1ada34
--- /dev/null
+++ b/consume/pecsplit.rs
@@ -0,0 +1,85 @@
+/* TODO: this needs an actual Rust person to review it first. I am a Rust newbie. */
+
+use std::ffi::OsString;
+use std::path::PathBuf;
+use std::os::unix::ffi::{OsStrExt, OsStringExt}; // TODO: windows
+
+fn pathbuf_to_u8(path: &PathBuf) -> &[u8] {
+  path.as_os_str().as_bytes() // TODO: windows
+}
+
+/* the polymorphism is to handle u8 (POSIX) and u16 (windows) */
+fn dequote<T>(s: &[T]) -> Vec<T> where u16: From<T>, T: From<u8>, T: Copy {
+  let mut v = Vec::with_capacity(s.len());
+  let mut escaped = false;
+  for c in s {
+    v.push(*c);
+    let c16 = u16::from(*c);
+    match c16 {
+      0x3A /* : */ => unreachable!(),
+      0x3D /* = */ => unreachable!(),
+      _ => if escaped {
+        match c16 {
+          0x70 /* p */ => { v.pop(); v.pop(); v.push(T::from(b'%')) },
+          0x65 /* e */ => { v.pop(); v.pop(); v.push(T::from(b'=')) },
+          0x63 /* c */ => { v.pop(); v.pop(); v.push(T::from(b':')) },
+          _ => (),
+        }
+      }
+    }
+    escaped = c16 == 0x25
+  }
+  v.shrink_to_fit();
+  v
+}
+
+fn decode(prefix_str: Option<OsString>) -> Result<Vec<(PathBuf, PathBuf)>, &'static str> {
+  prefix_str.unwrap_or(OsString::new())
+    .as_os_str().as_bytes() // TODO: windows
+    .split(|b| *b == b':')
+    .filter(|part| !part.is_empty())
+    .map(|part| {
+      let tuple = part
+        .split(|b| *b == b'=')
+        .collect::<Vec<_>>();
+      if tuple.len() != 2 {
+        Err("either too few or too many '='")
+      } else {
+        // TODO: windows
+        let src = OsString::from_vec(dequote(tuple[0]));
+        let dst = OsString::from_vec(dequote(tuple[1]));
+        Ok((PathBuf::from(src), PathBuf::from(dst)))
+      }
+    })
+    .collect::<Result<Vec<_>, _>>()
+}
+
+fn map_prefix(path: PathBuf, pm: &Vec<(PathBuf, PathBuf)>) -> PathBuf {
+  for pair in pm.iter().rev() {
+    let (ref src, ref dst) = *pair;
+    if path.starts_with(src) {
+      /* FIXME: this is different from what our other language examples do;
+       * rust's PathBuf.starts_with only matches whole components. however
+       * these all behave the same for our test cases.
+       */
+      return dst.join(path.strip_prefix(src).unwrap())
+    }
+  }
+  path
+}
+
+fn main() {
+  use std::env;
+  use std::io::{Write, stdout};
+
+  let pm = decode(env::var_os("BUILD_PATH_PREFIX_MAP"))
+    .unwrap_or_else(|_| std::process::exit(1));
+
+  //use std::io::Write;
+  //writeln!(&mut std::io::stderr(), "pm = {:?}", pm).unwrap();
+  for arg in env::args_os().skip(1) {
+    let path = map_prefix(PathBuf::from(arg), &pm);
+    stdout().write_all(pathbuf_to_u8(&path)).unwrap();
+    stdout().write_all(b"\n").unwrap();
+  }
+}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/reproducible/build-path-prefix-map-spec.git



More information about the Reproducible-commits mailing list