/*
* Copyright 2013 Thomas Bocek, Maxat Pernebayev
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package net.tomp2p.synchronization;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.List;
import net.tomp2p.peers.Number160;
import net.tomp2p.storage.AlternativeCompositeByteBuf;
import net.tomp2p.storage.DataBuffer;
public class SyncUtils {
public static List<Instruction> decodeInstructions(ByteBuf buf) {
List<Instruction> result = new ArrayList<Instruction>();
while(buf.isReadable()) {
final int header = buf.readInt();
if((header & 0x80000000) != 0) {
//first bit set, we have a reference
final int reference = header & 0x7FFFFFFF;
result.add(new Instruction(reference));
} else {
//otherwise the header is the length
final int length = header;
final int remaining = Math.min(length, buf.readableBytes());
DataBuffer literal = new DataBuffer(buf.slice(buf.readerIndex(), remaining));
buf.skipBytes(remaining);
result.add(new Instruction(literal));
}
}
return result;
}
public static Number160 decodeHeader(ByteBuf buf) {
byte[] me = new byte[Number160.BYTE_ARRAY_SIZE];
buf.readBytes(me);
return new Number160(me);
}
public static int encodeInstructions(List<Instruction> instructions, Number160 versionKey,
Number160 hash, AlternativeCompositeByteBuf buf) {
int size = 0;
buf.writeBytes(versionKey.toByteArray());
buf.writeBytes(hash.toByteArray());
//first bit to 1 means reference, otherwise length of the literal
for(Instruction instruction:instructions) {
int header = instruction.reference();
size +=4;
if(header != -1) {
header = header | (1<<31);
buf.writeInt(header);
} else {
header = instruction.length();
size += header;
//no need to clear flag
buf.writeInt(header);
instruction.literal().transferTo(buf);
}
}
return size;
}
public static DataBuffer encodeChecksum(List<Checksum> checksums, Number160 versionKey, Number160 hash, ByteBuf buf) {
buf.writeBytes(versionKey.toByteArray());
buf.writeBytes(hash.toByteArray());
for(Checksum checksum:checksums) {
buf.writeInt(checksum.weakChecksum());
buf.writeBytes(checksum.strongChecksum());
}
return new DataBuffer(buf);
}
public static List<Checksum> decodeChecksums(ByteBuf buf) {
final List<Checksum> result = new ArrayList<Checksum>();
while(buf.isReadable()) {
//16 bytes as its a MD5
final byte[] me = new byte[16];
final int weak = buf.readInt();
buf.readBytes(me);
result.add(new Checksum(weak, me));
}
return result;
}
}