Skip to content

Commit

Permalink
fix for encoding of Transferable schemas (#2027)
Browse files Browse the repository at this point in the history
  • Loading branch information
tim-smart authored and gcanti committed Feb 5, 2024
1 parent 7f1c1af commit 91dc611
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 18 deletions.
5 changes: 5 additions & 0 deletions .changeset/ten-pandas-brake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@effect/platform": minor
---

fix for encoding of Transferable schemas
44 changes: 29 additions & 15 deletions packages/platform/src/Transferable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,57 +37,71 @@ export const get = (u: unknown): ReadonlyArray<globalThis.Transferable> => {
return []
}

/**
* @since 1.0.0
* @category schema
*/
export interface TransferableSchema<A extends object, I, R> extends Schema.Schema<A & Transferable, I, R> {
(_: A): A & Transferable
}

/**
* @since 1.0.0
* @category schema
*/
export const schema: {
<A extends object>(
f: (_: A) => ReadonlyArray<globalThis.Transferable>
): <R, I>(self: Schema.Schema<A, I, R>) => Schema.Schema<A, I, R>
): <R, I>(self: Schema.Schema<A, I, R>) => TransferableSchema<A, I, R>
<R, I, A extends object>(
self: Schema.Schema<A, I, R>,
f: (_: A) => ReadonlyArray<globalThis.Transferable>
): Schema.Schema<A, I, R>
): TransferableSchema<A, I, R>
} = dual(2, <R, I, A extends object>(
self: Schema.Schema<A, I, R>,
f: (_: A) => ReadonlyArray<globalThis.Transferable>
) => {
const fn: Transferable[typeof symbol] = function(this: A) {
return f(this)
}
return Schema.transform(
const schema = Schema.transform(
self,
schemaFromSelf(Schema.to(self)),
(input) => addProxy(input, fn),
identity
)
function make(self: A): A & Transferable {
return addProxy(self, fn)
}
Object.setPrototypeOf(make, Object.getPrototypeOf(schema))
make.ast = schema.ast
return make
})

const schemaParse =
<R, A extends object>(parse: ParseResult.DecodeUnknown<R, A>): ParseResult.DeclarationDecodeUnknown<R, A> =>
(u, options, ast) => {
if (!isTransferable(u)) {
return ParseResult.fail(ParseResult.type(ast, u))
}
const f = u[symbol]
return ParseResult.map(parse(u, options), (a): A => addProxy(a, f))
const schemaParse = <R, A extends object>(
parse: ParseResult.DecodeUnknown<R, A>
): ParseResult.DeclarationDecodeUnknown<R, A & Transferable> =>
(u, options, ast) => {
if (!isTransferable(u)) {
return ParseResult.fail(ParseResult.type(ast, u))
}
const f = u[symbol]
return ParseResult.map(parse(u, options), (a) => addProxy(a, f))
}

/**
* @since 1.0.0
* @category schema
*/
export const schemaFromSelf = <R, I extends object, A extends object>(
export const schemaFromSelf = <A extends object, I extends object, R>(
item: Schema.Schema<A, I, R>
): Schema.Schema<A, I, R> => {
return Schema.declare(
): Schema.Schema<A & Transferable, I & Transferable, R> =>
Schema.declare(
[item],
(item) => schemaParse(ParseResult.decodeUnknown(item)),
(item) => schemaParse(ParseResult.encodeUnknown(item)),
{ identifier: "Transferable" }
)
}

const addProxy = <A extends object>(self: A, f: Transferable[typeof symbol]): A & Transferable => {
return new Proxy(self, {
Expand Down
32 changes: 29 additions & 3 deletions packages/platform/test/Transferable.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ import * as Transferable from "@effect/platform/Transferable"
import { Schema } from "@effect/schema"
import { assert, describe, test } from "vitest"

const TransferableUint8Array = Transferable.schema(
Schema.Uint8ArrayFromSelf,
(_) => [_.buffer]
)

describe("Transferable", () => {
test("calls symbol", () => {
class Test implements Transferable.Transferable {
Expand All @@ -28,11 +33,32 @@ describe("Transferable", () => {

test("schema Uint8Array", () => {
const array = new Uint8Array([1, 2, 3])
const data = Schema.decodeSync(TransferableUint8Array)(array)
assert.deepEqual(Transferable.get(data), [array.buffer])
})

test("schema encode", () => {
const schema = Transferable.schema(
Schema.Uint8ArrayFromSelf,
(_) => [_.buffer]
Schema.struct({
data: Schema.Uint8ArrayFromSelf
}),
(_) => [_.data.buffer]
)
const data = Schema.decodeSync(schema)(array)
const array = new Uint8Array([1, 2, 3])
const data = schema({
data: array
})
assert.deepEqual(Transferable.get(data), [array.buffer])

const encoded = Schema.encodeSync(schema)(data)
assert.deepEqual(encoded, {
data: array
})
})

test("schema encode Uint8Array", () => {
const array = new Uint8Array([1, 2, 3])
const data = TransferableUint8Array(array)
assert.deepEqual(Transferable.get(data), [array.buffer])
})
})

0 comments on commit 91dc611

Please sign in to comment.