Skip to content

Instantly share code, notes, and snippets.

@teidesu
Created July 12, 2024 09:18
Show Gist options
  • Select an option

  • Save teidesu/199abcd47a3fb494564a2c41965be5ad to your computer and use it in GitHub Desktop.

Select an option

Save teidesu/199abcd47a3fb494564a2c41965be5ad to your computer and use it in GitHub Desktop.
deno ffi issue repro
FROM denoland/deno:alpine-1.44.3
WORKDIR /app
RUN apk add pcre2
USER deno
COPY . /app
CMD ["run", "-A", "--unstable-ffi", "main.ts"]
const library = Deno.dlopen('/usr/lib/libpcre2-8.so.0', {
pcre2_compile_8: {
parameters: ['buffer', 'usize', 'u32', 'pointer', 'pointer', 'pointer'],
result: 'pointer',
},
pcre2_substitute_8: {
parameters: [
'pointer',
'buffer',
'u32',
'u32',
'u32',
'pointer',
'pointer',
'buffer',
'u32',
'buffer',
'pointer',
],
result: 'i32',
},
} as const)
const PCRE2_UTF = 0x00080000
const PCRE2_SUBSTITUTE_EXTENDED = 0x00000200
const PCRE2_SUBSTITUTE_OVERFLOW_LENGTH = 0x00001000
const lastErr = new Uint32Array(1)
const lastErrPtr = Deno.UnsafePointer.of(lastErr)
const lastErrOffset = new Uint32Array(1)
const lastErrOffsetPtr = Deno.UnsafePointer.of(lastErrOffset)
const outLen = new Uint32Array(1)
const outLenPtr = Deno.UnsafePointer.of(outLen)
export function compile(pattern: string): Deno.PointerValue {
const patternBuf = new TextEncoder().encode(pattern)
const code = library.symbols.pcre2_compile_8(
patternBuf,
BigInt(patternBuf.byteLength),
PCRE2_UTF,
lastErrPtr,
lastErrOffsetPtr,
null,
)
if (!code) {
throw new Error(
`pcre2_compile_8 error: ${lastErr[0]}`,
)
}
return code
}
export function substitute(
code: Deno.PointerValue,
subject: string,
replacement: string,
global = false,
): string {
const subjectBuf = new TextEncoder().encode(subject)
const replacementBuf = new TextEncoder().encode(replacement)
let resultBuf = new Uint8Array(1024)
const flags =
PCRE2_SUBSTITUTE_EXTENDED |
PCRE2_SUBSTITUTE_OVERFLOW_LENGTH
outLen[0] = resultBuf.byteLength
let res = library.symbols.pcre2_substitute_8(
code,
subjectBuf,
subjectBuf.byteLength,
0,
flags,
null,
null,
replacementBuf,
replacementBuf.byteLength,
resultBuf,
outLenPtr,
)
if (res < 0) {
throw new Error(`pcre2_substitute_8 error: ${res}`)
}
return new TextDecoder().decode(resultBuf.slice(0, outLen[0]))
}
const re = compile('hello')
console.log(substitute(re, 'hello world', 'goodbye'))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment