A => src/revlogs/content.rs +25 -0
@@ 0,0 1,25 @@
+use std::fmt;
+
+#[derive(Debug)]
+pub enum RevlogContent {
+ Generic(Vec<u8>),
+}
+
+impl fmt::Display for RevlogContent {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let printable = match self {
+ RevlogContent::Generic(s) => match std::str::from_utf8(s) {
+ Ok(parsed) => parsed.to_string(),
+ Err(_) => s
+ .iter()
+ .map(|c| {
+ std::ascii::escape_default(*c)
+ .map(|b| b as char)
+ .collect::<String>()
+ })
+ .collect::<String>(),
+ },
+ };
+ write!(f, "{}", printable)
+ }
+}
A => src/revlogs/entry.rs +43 -0
@@ 0,0 1,43 @@
+use flate2::read::ZlibDecoder;
+use std::fmt;
+use std::fs::File;
+use std::io;
+use std::io::Read;
+
+use super::content::RevlogContent;
+use super::header::RevlogHeader;
+
+#[derive(Debug)]
+pub struct RevlogEntry {
+ pub header: RevlogHeader,
+ pub content: RevlogContent,
+}
+
+impl RevlogEntry {
+ pub fn new(f: &mut File, header_buffer: &[u8; 64]) -> Result<RevlogEntry, io::Error> {
+ let header = RevlogHeader::new(&header_buffer)?;
+ let mut content_buffer = vec![0u8; header.compressedlength as usize];
+ f.read_exact(&mut content_buffer)?;
+ let decompressed_data = match content_buffer[0] {
+ 0 => vec![0u8; 0],
+ 0x75 => content_buffer[1..].to_vec(),
+ 0x78 => {
+ let mut gz = ZlibDecoder::new(&content_buffer[..]);
+ let mut decompressed_data = String::new();
+ gz.read_to_string(&mut decompressed_data)?;
+ decompressed_data.into_bytes()
+ }
+ _ => panic!(),
+ };
+ Ok(RevlogEntry {
+ header: header,
+ content: RevlogContent::Generic(decompressed_data),
+ })
+ }
+}
+
+impl fmt::Display for RevlogEntry {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "header:\n{}\ncontent: {}\n", self.header, self.content)
+ }
+}
A => +66 -0
@@ 0,0 1,66 @@
+use byteorder::{BigEndian, ReadBytesExt};
+use std::fmt;
+use std::io;
+use std::io::Cursor;
+use std::io::Read;
+
+#[derive(Debug)]
+pub struct RevlogHeader {
+ pub offset: u64, // really 6 bytes but easier to represent as a u64
+ pub bitflags: [u8; 2],
+ pub compressedlength: u32,
+ pub uncompressedlength: u32,
+ pub baserev: i32,
+ pub linkrev: i32,
+ pub p1rev: i32,
+ pub p2rev: i32,
+ pub hash: [u8; 32],
+}
+
+impl RevlogHeader {
+ pub fn new(buffer: &[u8; 64]) -> Result<RevlogHeader, io::Error> {
+ let mut cursor = Cursor::new(buffer as &[u8]);
+ Ok(RevlogHeader {
+ offset: cursor.read_u48::<BigEndian>()? as u64,
+ bitflags: cursor.read_u16::<BigEndian>()?.to_be_bytes(),
+ compressedlength: cursor.read_u32::<BigEndian>()?,
+ uncompressedlength: cursor.read_u32::<BigEndian>()?,
+ baserev: cursor.read_i32::<BigEndian>()?,
+ linkrev: cursor.read_i32::<BigEndian>()?,
+ p1rev: cursor.read_i32::<BigEndian>()?,
+ p2rev: cursor.read_i32::<BigEndian>()?,
+ hash: {
+ let mut res = [0u8; 32];
+ cursor.read_exact(&mut res)?;
+ res
+ },
+ })
+ }
+}
+
+impl fmt::Display for RevlogHeader {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let hash: Vec<String> = self.hash.iter().map(|b| format!("{:02x}", b)).collect();
+ write!(
+ f,
+ "offset: {}\n\
+ bitflags: {:?}\n\
+ compressed length: {}\n\
+ uncompressed length: {}\n\
+ base revision: {}\n\
+ linked revision: {}\n\
+ p1: {}\n\
+ p2: {}\n\
+ hash: {}\n",
+ self.offset,
+ self.bitflags,
+ self.compressedlength,
+ self.uncompressedlength,
+ self.baserev,
+ self.linkrev,
+ self.p1rev,
+ self.p2rev,
+ hash.join("")
+ )
+ }
+}
M src/revlogs/mod.rs +8 -122
@@ 1,131 1,17 @@
-use byteorder::{BigEndian, ReadBytesExt};
-use flate2::read::ZlibDecoder;
use std::fmt;
use std::fs::File;
use std::io;
-use std::io::prelude::*;
-use std::io::Cursor;
+use std::io::Read;
+use std::io::Seek;
use std::io::SeekFrom;
-#[derive(Debug)]
-struct RevlogHeader {
- offset: u64, // really 6 bytes but easier to represent as a u64
- bitflags: [u8; 2],
- compressedlength: u32,
- uncompressedlength: u32,
- baserev: i32,
- linkrev: i32,
- p1rev: i32,
- p2rev: i32,
- hash: [u8; 32],
-}
-
-impl RevlogHeader {
- fn new(buffer: &[u8; 64]) -> Result<RevlogHeader, io::Error> {
- let mut cursor = Cursor::new(buffer as &[u8]);
- Ok(RevlogHeader {
- offset: cursor.read_u48::<BigEndian>()? as u64,
- bitflags: cursor.read_u16::<BigEndian>()?.to_be_bytes(),
- compressedlength: cursor.read_u32::<BigEndian>()?,
- uncompressedlength: cursor.read_u32::<BigEndian>()?,
- baserev: cursor.read_i32::<BigEndian>()?,
- linkrev: cursor.read_i32::<BigEndian>()?,
- p1rev: cursor.read_i32::<BigEndian>()?,
- p2rev: cursor.read_i32::<BigEndian>()?,
- hash: {
- let mut res = [0u8; 32];
- cursor.read_exact(&mut res)?;
- res
- },
- })
- }
-}
-
-#[derive(Debug)]
-struct RevlogEntry {
- header: RevlogHeader,
- content: RevlogContent,
-}
-
-#[derive(Debug)]
-enum RevlogContent {
- Generic(Vec<u8>),
-}
+pub mod content;
+pub mod entry;
+pub mod header;
-impl RevlogEntry {
- fn new(f: &mut File, header_buffer: &[u8; 64]) -> Result<RevlogEntry, io::Error> {
- let header = RevlogHeader::new(&header_buffer)?;
- let mut content_buffer = vec![0u8; header.compressedlength as usize];
- f.read_exact(&mut content_buffer)?;
- let decompressed_data = match content_buffer[0] {
- 0 => vec![0u8; 0],
- 0x75 => content_buffer[1..].to_vec(),
- 0x78 => {
- let mut gz = ZlibDecoder::new(&content_buffer[..]);
- let mut decompressed_data = String::new();
- gz.read_to_string(&mut decompressed_data)?;
- decompressed_data.into_bytes()
- }
- _ => panic!(),
- };
- Ok(RevlogEntry {
- header: header,
- content: RevlogContent::Generic(decompressed_data),
- })
- }
-}
-
-impl fmt::Display for RevlogHeader {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let hash: Vec<String> = self.hash.iter().map(|b| format!("{:02x}", b)).collect();
- write!(
- f,
- "offset: {}\n\
- bitflags: {:?}\n\
- compressed length: {}\n\
- uncompressed length: {}\n\
- base revision: {}\n\
- linked revision: {}\n\
- p1: {}\n\
- p2: {}\n\
- hash: {}\n",
- self.offset,
- self.bitflags,
- self.compressedlength,
- self.uncompressedlength,
- self.baserev,
- self.linkrev,
- self.p1rev,
- self.p2rev,
- hash.join("")
- )
- }
-}
-
-impl fmt::Display for RevlogEntry {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "header:\n{}\ncontent: {}\n", self.header, self.content)
- }
-}
-
-impl fmt::Display for RevlogContent {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let printable = match self {
- RevlogContent::Generic(s) => match std::str::from_utf8(s) {
- Ok(parsed) => parsed.to_string(),
- Err(_) => s
- .iter()
- .map(|c| {
- std::ascii::escape_default(*c)
- .map(|b| b as char)
- .collect::<String>()
- })
- .collect::<String>(),
- },
- };
- write!(f, "{}", printable)
- }
-}
+pub use content::RevlogContent;
+pub use entry::RevlogEntry;
+pub use header::RevlogHeader;
#[derive(Debug)]
pub struct Revlog {