LinusU / swift-napi-bindings

MIT License
29 stars 0 forks source link

Need help with Data ValueConvertible #3

Open camhart opened 4 years ago

camhart commented 4 years ago

I'm new to swift, c, c++, and napi. So forgive the noobyness. I need to pass an object containing a Data (https://developer.apple.com/documentation/foundation/data) object from swift to nodejs (passing image data).

End goal would be Data on nodejs side as a byte array/buffer.

import NAPI
import NAPIC
import Foundation
import Cocoa

open class ScreenWithScreenshot : NAPI.ValueConvertible {

    public let screenshotData : Data
    public let screenIndex : Int
    public let screenRect : NSRect
    public let scale : CGFloat

    public required init(_ screenIndex : Int, _ screen : NSScreen, _ screenshotData : Data) {
        self.screenIndex = screenIndex
        self.screenshotData = screenshotData
        self.screenRect = CoordinateHelper.GetQuartzCoordinates(screen)
        self.scale = screen.backingScaleFactor
    }

    public required convenience init(_ env: napi_env, from: napi_value) throws {
        fatalError("Not implemented")
    }

    public func napiValue(_ env: napi_env) throws -> napi_value {

        var result: napi_value!
        var status: napi_status!

        status = napi_create_object(env, &result)
        guard status == napi_ok else { throw NAPI.Error(status) }

        var screenIndex: napi_value!
        status = napi_create_int32(env, Int32(self.screenIndex), &screenIndex)
        guard status == napi_ok else { throw NAPI.Error(status) }

        status = napi_set_named_property(env, result, "screenIndex", screenIndex)
        guard status == napi_ok else { throw NAPI.Error(status) }

        status = napi_set_named_property(env, result, "screenRect", try self.screenRect.napiValue(env))
        guard status == napi_ok else { throw NAPI.Error(status) }

        var scale: napi_value!
        status = napi_create_double(env, Double(self.scale), &scale)
        guard status == napi_ok else { throw NAPI.Error(status) }

        status = napi_set_named_property(env, result, "scale", scale)
        guard status == napi_ok else { throw NAPI.Error(status) }

//          //struggling here
//         var data: napi_value!
//         status = napi_set_named_property(env, result, "data", self.screenshotData.bytes
//         guard status == napi_ok else { throw NAPI.Error(status) }

        return result
    }
}

Extensions:

import NAPI
import NAPIC
import Foundation
import Cocoa

extension NSRect: NAPI.ValueConvertible {
    public init(_ env: napi_env, from: napi_value) throws {
        fatalError("Not implemented")
    }

    public func napiValue(_ env: napi_env) throws -> napi_value {
        var status: napi_status!
        var result: napi_value!

        status = napi_create_object(env, &result)
        guard status == napi_ok else { throw NAPI.Error(status) }

        var x: napi_value!
        status = napi_create_double(env, Double(self.minX), &x)
        guard status == napi_ok else { throw NAPI.Error(status) }

        var y: napi_value!
        status = napi_create_double(env, Double(self.minY), &y)
        guard status == napi_ok else { throw NAPI.Error(status) }

        var width: napi_value!
        status = napi_create_double(env, Double(self.width), &width)
        guard status == napi_ok else { throw NAPI.Error(status) }

        var height: napi_value!
        status = napi_create_double(env, Double(self.height), &height)
        guard status == napi_ok else { throw NAPI.Error(status) }

        status = napi_set_named_property(env, result, "x", x)
        guard status == napi_ok else { throw NAPI.Error(status) }

        status = napi_set_named_property(env, result, "y", y)
        guard status == napi_ok else { throw NAPI.Error(status) }

        status = napi_set_named_property(env, result, "width", width)
        guard status == napi_ok else { throw NAPI.Error(status) }

        status = napi_set_named_property(env, result, "height", height)
        guard status == napi_ok else { throw NAPI.Error(status) }

        return result
    }

}

extension Data {
    var bytes : [UInt8] {
        return [UInt8](self)
    }
}
camhart commented 4 years ago

I figured out how to pass it as base64 encoded string. Still can't figure out how to just pass it as a raw byte array or buffer.

        let base64Data = self.screenshotData.base64EncodedString()
        status = napi_set_named_property(env, result, "data", try base64Data.napiValue(env))
        guard status == napi_ok else { throw NAPI.Error(status) }
LinusU commented 4 years ago

The best way forward would probably be to make Data conform to NAPI.ValueConvertible, and have it use the NAPI apis for creating Uint8Arrays. I don't have time to fix that right now, but would be happy to accept a PR 👍