Skip to content

Commit 8def703

Browse files
authored
feat(scw): add blob to scw file marshaler (#1367)
1 parent 365da9e commit 8def703

File tree

7 files changed

+189
-0
lines changed

7 files changed

+189
-0
lines changed

packages/clients/src/bridge.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export {
1616
marshalMoney,
1717
marshalTimeSeries,
1818
marshalDecimal,
19+
marshalBlobToScwFile,
1920
unmarshalMoney,
2021
unmarshalScwFile,
2122
unmarshalServiceInfo,

packages/clients/src/internals.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export {
1515
marshalScwFile,
1616
marshalMoney,
1717
marshalTimeSeries,
18+
marshalBlobToScwFile,
1819
unmarshalDecimal,
1920
unmarshalMoney,
2021
unmarshalScwFile,

packages/clients/src/scw/custom-marshalling.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { isJSONObject } from '../helpers/json'
22
import { unmarshalArrayOfObject, unmarshalDate } from '../helpers/marshalling'
3+
import { fromByteArray } from '../vendor/base64'
34
import type {
45
Money,
56
ScwFile,
@@ -134,6 +135,19 @@ export const marshalScwFile = (obj: ScwFile): Record<string, unknown> => ({
134135
name: obj.name,
135136
})
136137

138+
/**
139+
* Marshals {@link Blob}.
140+
*
141+
* @internal
142+
*/
143+
export const marshalBlobToScwFile = async (
144+
blob: Blob,
145+
): Promise<Record<string, unknown>> => ({
146+
content: fromByteArray(new Uint8Array(await blob.arrayBuffer())),
147+
content_type: blob.type,
148+
name: 'file',
149+
})
150+
137151
/**
138152
* Marshals {@link Money}
139153
*
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2014 Jameson Little
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in
13+
all copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
THE SOFTWARE.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# base64
2+
3+
This code is vendored from [github](https://github.com/beatgammit/base64-js)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function byteLength(b64: string): number
2+
export function toByteArray(b64: string): Uint8Array
3+
export function fromByteArray(uint8: Uint8Array): string
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
'use strict'
2+
3+
var lookup = []
4+
var revLookup = []
5+
var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array
6+
7+
var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
8+
for (var i = 0, len = code.length; i < len; ++i) {
9+
lookup[i] = code[i]
10+
revLookup[code.charCodeAt(i)] = i
11+
}
12+
13+
// Support decoding URL-safe base64 strings, as Node.js does.
14+
// See: https://en.wikipedia.org/wiki/Base64#URL_applications
15+
revLookup['-'.charCodeAt(0)] = 62
16+
revLookup['_'.charCodeAt(0)] = 63
17+
18+
function getLens (b64) {
19+
var len = b64.length
20+
21+
if (len % 4 > 0) {
22+
throw new Error('Invalid string. Length must be a multiple of 4')
23+
}
24+
25+
// Trim off extra bytes after placeholder bytes are found
26+
// See: https://github.com/beatgammit/base64-js/issues/42
27+
var validLen = b64.indexOf('=')
28+
if (validLen === -1) validLen = len
29+
30+
var placeHoldersLen = validLen === len
31+
? 0
32+
: 4 - (validLen % 4)
33+
34+
return [validLen, placeHoldersLen]
35+
}
36+
37+
// base64 is 4/3 + up to two characters of the original data
38+
export function byteLength (b64) {
39+
var lens = getLens(b64)
40+
var validLen = lens[0]
41+
var placeHoldersLen = lens[1]
42+
return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen
43+
}
44+
45+
function _byteLength (b64, validLen, placeHoldersLen) {
46+
return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen
47+
}
48+
49+
export function toByteArray (b64) {
50+
var tmp
51+
var lens = getLens(b64)
52+
var validLen = lens[0]
53+
var placeHoldersLen = lens[1]
54+
55+
var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen))
56+
57+
var curByte = 0
58+
59+
// if there are placeholders, only get up to the last complete 4 chars
60+
var len = placeHoldersLen > 0
61+
? validLen - 4
62+
: validLen
63+
64+
var i
65+
for (i = 0; i < len; i += 4) {
66+
tmp =
67+
(revLookup[b64.charCodeAt(i)] << 18) |
68+
(revLookup[b64.charCodeAt(i + 1)] << 12) |
69+
(revLookup[b64.charCodeAt(i + 2)] << 6) |
70+
revLookup[b64.charCodeAt(i + 3)]
71+
arr[curByte++] = (tmp >> 16) & 0xFF
72+
arr[curByte++] = (tmp >> 8) & 0xFF
73+
arr[curByte++] = tmp & 0xFF
74+
}
75+
76+
if (placeHoldersLen === 2) {
77+
tmp =
78+
(revLookup[b64.charCodeAt(i)] << 2) |
79+
(revLookup[b64.charCodeAt(i + 1)] >> 4)
80+
arr[curByte++] = tmp & 0xFF
81+
}
82+
83+
if (placeHoldersLen === 1) {
84+
tmp =
85+
(revLookup[b64.charCodeAt(i)] << 10) |
86+
(revLookup[b64.charCodeAt(i + 1)] << 4) |
87+
(revLookup[b64.charCodeAt(i + 2)] >> 2)
88+
arr[curByte++] = (tmp >> 8) & 0xFF
89+
arr[curByte++] = tmp & 0xFF
90+
}
91+
92+
return arr
93+
}
94+
95+
function tripletToBase64 (num) {
96+
return lookup[num >> 18 & 0x3F] +
97+
lookup[num >> 12 & 0x3F] +
98+
lookup[num >> 6 & 0x3F] +
99+
lookup[num & 0x3F]
100+
}
101+
102+
function encodeChunk (uint8, start, end) {
103+
var tmp
104+
var output = []
105+
for (var i = start; i < end; i += 3) {
106+
tmp =
107+
((uint8[i] << 16) & 0xFF0000) +
108+
((uint8[i + 1] << 8) & 0xFF00) +
109+
(uint8[i + 2] & 0xFF)
110+
output.push(tripletToBase64(tmp))
111+
}
112+
return output.join('')
113+
}
114+
115+
export function fromByteArray (uint8) {
116+
var tmp
117+
var len = uint8.length
118+
var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes
119+
var parts = []
120+
var maxChunkLength = 16383 // must be multiple of 3
121+
122+
// go through the array every three bytes, we'll deal with trailing stuff later
123+
for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
124+
parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)))
125+
}
126+
127+
// pad the end with zeros, but make sure to not forget the extra bytes
128+
if (extraBytes === 1) {
129+
tmp = uint8[len - 1]
130+
parts.push(
131+
lookup[tmp >> 2] +
132+
lookup[(tmp << 4) & 0x3F] +
133+
'=='
134+
)
135+
} else if (extraBytes === 2) {
136+
tmp = (uint8[len - 2] << 8) + uint8[len - 1]
137+
parts.push(
138+
lookup[tmp >> 10] +
139+
lookup[(tmp >> 4) & 0x3F] +
140+
lookup[(tmp << 2) & 0x3F] +
141+
'='
142+
)
143+
}
144+
145+
return parts.join('')
146+
}

0 commit comments

Comments
 (0)