1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
use {FileSet, FileUpdater, FileMetadata}; use lookup::IDLookup; use std::collections::hash_map::HashMap; use std::io; use std::path::PathBuf; use byteorder::{NetworkEndian, ByteOrder}; impl<FU: FileUpdater> FileSet<FU> { pub fn compress_to<W: io::Write>(&self, writer: &mut W) -> io::Result<()> { let mut int_buf = [0;4]; NetworkEndian::write_u32(&mut int_buf, self.last_timestamp); try!(writer.write(&int_buf)); NetworkEndian::write_u32(&mut int_buf, self.last_id); try!(writer.write(&int_buf)); NetworkEndian::write_u32(&mut int_buf, self.site_id); try!(writer.write(&int_buf)); NetworkEndian::write_u32(&mut int_buf, self.files.len() as u32); try!(writer.write(&int_buf)); for (&(site_id, id), file) in self.files.iter() { NetworkEndian::write_u32(&mut int_buf, site_id); try!(writer.write(&int_buf)); NetworkEndian::write_u32(&mut int_buf, id); try!(writer.write(&int_buf)); NetworkEndian::write_u32(&mut int_buf, file.filename.0); try!(writer.write(&int_buf)); NetworkEndian::write_u32(&mut int_buf, file.filename.1.len() as u32); try!(writer.write(&int_buf)); for filename in file.filename.1.iter() { let bytes = filename.as_bytes(); NetworkEndian::write_u32(&mut int_buf, bytes.len() as u32); try!(writer.write(&int_buf)); try!(writer.write(bytes)); } let bytes = file.printed_filename.as_bytes(); NetworkEndian::write_u32(&mut int_buf, bytes.len() as u32); try!(writer.write(&int_buf)); try!(writer.write(bytes)); NetworkEndian::write_u32(&mut int_buf, file.attributes.len() as u32); try!(writer.write(&int_buf)); for (key, &(time_stamp, ref value)) in file.attributes.iter() { let bytes = key.as_bytes(); NetworkEndian::write_u32(&mut int_buf, bytes.len() as u32); try!(writer.write(&int_buf)); try!(writer.write(bytes)); NetworkEndian::write_u32(&mut int_buf, time_stamp); try!(writer.write(&int_buf)); let bytes = value.as_bytes(); NetworkEndian::write_u32(&mut int_buf, bytes.len() as u32); try!(writer.write(&int_buf)); try!(writer.write(bytes)); } } Ok(()) } pub fn expand_from<R: io::Read>(reader: &mut R, updater: FU, storage_path: PathBuf) -> io::Result<FileSet<FU>> { trace!("Expanding Fileset"); let mut int_buf = [0;4]; try!(reader.read_exact(&mut int_buf)); let last_timestamp = NetworkEndian::read_u32(&int_buf); trace!("last_timestamp: {}", last_timestamp); try!(reader.read_exact(&mut int_buf)); let last_id = NetworkEndian::read_u32(&int_buf); trace!("last_id: {}", last_id); try!(reader.read_exact(&mut int_buf)); let site_id = NetworkEndian::read_u32(&int_buf); trace!("site_id: {}", site_id); try!(reader.read_exact(&mut int_buf)); let file_count = NetworkEndian::read_u32(&int_buf) as usize; trace!("file count: {}", file_count); let mut files = HashMap::with_capacity(file_count); let mut id_lookup = IDLookup::new(); for _ in 0..file_count { try!(reader.read_exact(&mut int_buf)); let file_site_id = NetworkEndian::read_u32(&int_buf); trace!("file site_id: {}", file_site_id); try!(reader.read_exact(&mut int_buf)); let id = NetworkEndian::read_u32(&int_buf); trace!("id: {}", id); try!(reader.read_exact(&mut int_buf)); let filename_timestamp = NetworkEndian::read_u32(&int_buf); trace!("filename_timestamp: {}", filename_timestamp); try!(reader.read_exact(&mut int_buf)); let filename_component_count = NetworkEndian::read_u32(&int_buf) as usize; let mut filename = Vec::with_capacity(filename_component_count); for _ in 0..filename_component_count { filename.push(read_str(reader, &mut int_buf).unwrap()) } trace!("filename: {:?}", filename); let printed_filename = try!(read_str(reader, &mut int_buf)); trace!("printed_filename: {}", printed_filename); try!(reader.read_exact(&mut int_buf)); let attribute_count = NetworkEndian::read_u32(&int_buf) as usize; trace!("attribute_count: {}", attribute_count); let mut attributes = HashMap::with_capacity(attribute_count); for _ in 0..attribute_count { let key = try!(read_str(reader, &mut int_buf)); try!(reader.read_exact(&mut int_buf)); let attribute_timestamp = NetworkEndian::read_u32(&int_buf); let value = try!(read_str(reader, &mut int_buf)); attributes.insert(key, (attribute_timestamp, value)); } let metadata = FileMetadata{ filename: (filename_timestamp, filename), printed_filename: printed_filename.clone(), attributes: attributes }; id_lookup.add_file(metadata.get_local_filename().iter(), (file_site_id, id), file_site_id); files.insert((file_site_id, id), metadata); } trace!("Fileset loaded"); Ok(FileSet { files: files, id_lookup: id_lookup, updater: updater, last_timestamp: last_timestamp, last_id: last_id, site_id: site_id, storage_path: storage_path }) } } fn read_str<R: io::Read>(reader: &mut R, int_buf: &mut [u8;4]) -> io::Result<String> { try!(reader.read_exact(int_buf)); let str_len = NetworkEndian::read_u32(int_buf) as usize; let mut str_vec:Vec<u8> = Vec::with_capacity(str_len); str_vec.resize(str_len, 0); try!(reader.read_exact(&mut str_vec)); Ok(String::from_utf8_lossy(str_vec.as_slice()).into_owned()) }