<commit_before>package peergos.shared.merklebtree;

import peergos.shared.cbor.*;
import peergos.shared.ipfs.api.*;
import peergos.shared.util.*;

import java.io.*;
import java.util.*;

public class MerkleNode {
    public final byte[] data;
    public final List<Link> links;

    public MerkleNode(byte[] data, List<Link> links) {
        this.data = data;
        this.links = links;
        Collections.sort(this.links);
    }

    public MerkleNode(byte[] data) {
        this(data, Collections.emptyList());
    }

    public static class Link implements Comparable<Link> {
        public final String label;
        public final Multihash target;

        public Link(String label, Multihash target) {
            this.label = label;
            this.target = target;
        }

        @Override
        public int compareTo(Link link) {
            return label.compareTo(link.label);
        }
    }

    public MerkleNode addLink(String label, Multihash linkTarget) {
        List<Link> tmp = new ArrayList<>(links);
        tmp.add(new Link(label, linkTarget));
        return new MerkleNode(data, tmp);
    }

    public MerkleNode setData(byte[] newData) {
        return new MerkleNode(newData, links);
    }

    /**
     *
     * @return a byte[] of the CBOR serialization of this merkle node
     */
    public byte[] serialize() {
        try {
            ByteArrayOutputStream bout = new ByteArrayOutputStream();
            CborEncoder encoder = new CborEncoder(bout);
            encoder.writeByteString(data);
            encoder.writeInt8(links.size());
            for (Link link: links) {
                encoder.writeTextString(link.label);
                encoder.writeByteString(link.target.toBytes());
            }
            return bout.toByteArray();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     *
     * @param in a CBOR encoding of a merkle node
     * @return
     * @throws IOException for an invalid encoding
     */
    public static MerkleNode deserialize(byte[] in) throws IOException {
        CborDecoder decoder = new CborDecoder(new ByteArrayInputStream(in));
        byte[] data = decoder.readByteString();
        List<Link> links = new ArrayList<>();
        int nLinks = decoder.readInt8();
        for (int i = 0; i < nLinks; i++) {
            String label = decoder.readTextString();
            Multihash target = Multihash.deserialize(new DataSource(decoder.readByteString()));
            links.add(new Link(label, target));
        }
        return new MerkleNode(data, links);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        MerkleNode that = (MerkleNode) o;

        if (!Arrays.equals(data, that.data)) return false;
        return links != null ? links.equals(that.links) : that.links == null;

    }

    @Override
    public int hashCode() {
        int result = Arrays.hashCode(data);
        result = 31 * result + (links != null ? links.hashCode() : 0);
        return result;
    }
}<commit_msg>Change CBOR format to match what I think IPFS's is<commit_after>package peergos.shared.merklebtree;

import peergos.shared.cbor.*;
import peergos.shared.ipfs.api.*;
import peergos.shared.util.*;

import java.io.*;
import java.util.*;

public class MerkleNode {
    public final byte[] data;
    public final List<Link> links;

    public MerkleNode(byte[] data, List<Link> links) {
        this.data = data;
        this.links = links;
        Collections.sort(this.links);
    }

    public MerkleNode(byte[] data) {
        this(data, Collections.emptyList());
    }

    public static class Link implements Comparable<Link> {
        public final String label;
        public final Multihash target;

        public Link(String label, Multihash target) {
            this.label = label;
            this.target = target;
        }

        @Override
        public int compareTo(Link link) {
            return label.compareTo(link.label);
        }
    }

    public MerkleNode addLink(String label, Multihash linkTarget) {
        List<Link> tmp = new ArrayList<>(links);
        tmp.add(new Link(label, linkTarget));
        return new MerkleNode(data, tmp);
    }

    public MerkleNode setData(byte[] newData) {
        return new MerkleNode(newData, links);
    }

    /**
     *
     * @return a byte[] of the CBOR serialization of this merkle node
     */
    public byte[] serialize() {
        try {
            ByteArrayOutputStream bout = new ByteArrayOutputStream();
            CborEncoder encoder = new CborEncoder(bout);
            encoder.writeMapStart(1 + links.size());
            encoder.writeTextString("Data");
            encoder.writeByteString(data);
            for (Link link: links) {
                encoder.writeTextString(link.label);
                encoder.writeByteString(link.target.toBytes());
            }
            return bout.toByteArray();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     *
     * @param in a CBOR encoding of a merkle node
     * @return
     * @throws IOException for an invalid encoding
     */
    public static MerkleNode deserialize(byte[] in) throws IOException {
        CborDecoder decoder = new CborDecoder(new ByteArrayInputStream(in));
        long elements = decoder.readMapLength();
        String dataLabel = decoder.readTextString();
        byte[] data = decoder.readByteString();
        List<Link> links = new ArrayList<>();
        for (int i = 0; i < elements - 1; i++) {
            String label = decoder.readTextString();
            Multihash target = Multihash.deserialize(new DataSource(decoder.readByteString()));
            links.add(new Link(label, target));
        }
        return new MerkleNode(data, links);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        MerkleNode that = (MerkleNode) o;

        if (!Arrays.equals(data, that.data)) return false;
        return links != null ? links.equals(that.links) : that.links == null;

    }

    @Override
    public int hashCode() {
        int result = Arrays.hashCode(data);
        result = 31 * result + (links != null ? links.hashCode() : 0);
        return result;
    }
}
{'fraction_non_alphanumeric': 0.11095614442894777, 'fraction_numerical': 0.0018596001859600185, 'mean_word_length': 2.220558882235529, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3946385', 'n_tokens_mistral': 1833, 'n_tokens_neox': 1801, 'n_words': 493}