XYOracleNetwork/sdk-core-swift

View on GitHub
Sources/sdk-core-swift/objectmodel/XyoObjectStructure.swift

Summary

Maintainability
C
7 hrs
Test Coverage
//
//  XyoObjectStructure.swift
//  sdk-objectmodel-swift
//
//  Created by Carter Harrison on 1/21/19.
//  Copyright © 2019 XYO Network. All rights reserved.
//

import Foundation

open class XyoObjectStructure {
    private let typedSchema: XyoObjectSchema?
    var value: XyoBuffer

    public init (value: XyoBuffer) {
        self.typedSchema = nil
        self.value = value
    }

    public init (value: XyoBuffer, schema: XyoObjectSchema) {
        self.typedSchema = schema
        self.value = XyoBuffer().put(schema: schema).put(buffer: value)
    }

    public func getBuffer () -> XyoBuffer {
        return value
    }

    public func getSchema () throws -> XyoObjectSchema {
        return typedSchema ?? value.getSchema(offset: 0)
    }

    public func getValueCopy () throws -> XyoBuffer {
        let startIndex = 2 + (try getSchema()).getSizeIdentifier().rawValue + value.allowedOffset
        let endIndex = startIndex + (try getSize()) - (try getSchema()).getSizeIdentifier().rawValue
        try checkIndex(index: endIndex -  value.allowedOffset)

        return XyoBuffer(data: value, allowedOffset: startIndex, lastOffset: endIndex)
    }

    public func getSize () throws -> Int {
        let sizeOfSize = Int(try getSchema().getSizeIdentifier().rawValue)
        try checkIndex(index: sizeOfSize + 2)
        return readSizeOfObject(sizeIdentifier: (try getSchema()).getSizeIdentifier(), offset: 2)
    }

    internal func checkIndex (index: Int) throws {
        if index > value.getSize() {
            throw XyoObjectError.OUTOFINDEX
        }
    }

    func readSizeOfObject (sizeIdentifier: XyoObjectSize, offset: Int) -> Int {
        switch sizeIdentifier {
        case XyoObjectSize.ONE:
            return Int(value.getUInt8(offset: offset))
        case XyoObjectSize.TWO:
            return Int(value.getUInt16(offset: offset))
        case XyoObjectSize.FOUR:
            return Int(value.getUInt32(offset: offset))
        case XyoObjectSize.EIGHT:
            return Int(value.getUInt64(offset: offset))
        }
    }

    public static func newInstance (schema: XyoObjectSchema, bytes: XyoBuffer) -> XyoObjectStructure {
        return XyoObjectStructure(value: encode(schema: schema, bytes: bytes))
    }

    static func encode (schema: XyoObjectSchema, bytes: XyoBuffer) -> XyoBuffer {
        let buffer = XyoBuffer()
        let size = bytes.toByteArray().count
        let typeOfSize = XyoByteUtil.getBestSize(size: size)
        buffer.put(schema: XyoObjectSchema.create(id: schema.id,
                                                  isIterable: schema.getIsIterable(),
                                                  isTypedIterable: schema.getIsTypedIterable(),
                                                  sizeIdentifier: typeOfSize))

        switch typeOfSize {
        case XyoObjectSize.ONE:
            buffer.put(bits: UInt8(size + 1))
        case XyoObjectSize.TWO:
            buffer.put(bits: UInt16(size + 2))
        case XyoObjectSize.FOUR:
            buffer.put(bits: UInt32(size + 4))
        case XyoObjectSize.EIGHT:
            buffer.put(bits: UInt64(size + 8))
        }

        return buffer.put(bytes: bytes.toByteArray())
    }
}