- 홈
- Documentation
- 네이티브
- 네이티브 미디어 + 시스템 유틸리티
네이티브 미디어 + 시스템 유틸리티
이 문서는 docs/natives-architecture.md에 설명된 system/media/conversion primitives 계층에 대한 서브시스템 심층 분석입니다: image, html, clipboard, 그리고 work 프로파일링을 다룹니다.
구현 파일
섹션 제목: “구현 파일”crates/pi-natives/src/image.rscrates/pi-natives/src/html.rscrates/pi-natives/src/clipboard.rscrates/pi-natives/src/prof.rscrates/pi-natives/src/task.rspackages/natives/src/image/index.tspackages/natives/src/image/types.tspackages/natives/src/html/index.tspackages/natives/src/html/types.tspackages/natives/src/clipboard/index.tspackages/natives/src/clipboard/types.tspackages/natives/src/work/index.tspackages/natives/src/work/types.ts
참고:
crates/pi-natives/src/work.rs는 존재하지 않습니다. 작업 프로파일링은prof.rs에서 구현되며task.rs의 계측에 의해 데이터가 공급됩니다.
TS API ↔ Rust export/module 매핑
섹션 제목: “TS API ↔ Rust export/module 매핑”| TS export (packages/natives) | Rust N-API export | Rust 모듈 |
|---|---|---|
PhotonImage.parse(bytes) | PhotonImage::parse | image.rs |
PhotonImage#resize(width, height, filter) | PhotonImage::resize | image.rs |
PhotonImage#encode(format, quality) | PhotonImage::encode | image.rs |
htmlToMarkdown(html, options) | html_to_markdown | html.rs |
copyToClipboard(text) | copy_to_clipboard + TS 폴백 로직 | clipboard.rs + clipboard/index.ts |
readImageFromClipboard() | read_image_from_clipboard | clipboard.rs |
getWorkProfile(lastSeconds) | get_work_profile | prof.rs |
데이터 형식 경계 및 변환
섹션 제목: “데이터 형식 경계 및 변환”이미지 (image)
섹션 제목: “이미지 (image)”- JS 입력 경계:
Uint8Array인코딩된 이미지 바이트. - Rust 디코드 경계: 바이트가
Vec<u8>로 복사되고,ImageReader::with_guessed_format()으로 형식이 추측된 후DynamicImage로 디코딩됩니다. - 메모리 내 상태:
PhotonImage는Arc<DynamicImage>를 저장합니다. - 출력 경계:
encode(format, quality)는Promise<Uint8Array>(RustVec<u8>)를 반환합니다.
형식 ID는 숫자입니다:
0: PNG1: JPEG2: WebP (무손실 인코더)3: GIF
제약 조건:
quality는 JPEG에서만 사용됩니다.- PNG/WebP/GIF는
quality를 무시합니다. - 지원되지 않는 형식 ID는 실패합니다 (
Invalid image format: <id>).
HTML 변환 (html)
섹션 제목: “HTML 변환 (html)”- JS 입력 경계: HTML
string+ 선택적 객체{ cleanContent?: boolean; skipImages?: boolean }. - Rust 변환 경계:
String입력이html_to_markdown_rs::convert에 의해 변환됩니다. - 출력 경계: Markdown
string.
변환 동작:
cleanContent의 기본값은false입니다.cleanContent=true일 때,PreprocessingPreset::Aggressive와 네비게이션/폼에 대한 하드 제거 플래그가 포함된 전처리가 활성화됩니다.skipImages의 기본값은false입니다.
클립보드 (clipboard)
섹션 제목: “클립보드 (clipboard)”- 텍스트 경로:
- TS는 stdout이 TTY일 때 먼저 OSC 52 (
\x1b]52;c;<base64>\x07)를 출력합니다. - 동일한 텍스트가 최선 노력 방식으로 네이티브 클립보드 API (
native.copyToClipboard)를 통해 시도됩니다. - Termux에서는 TS가 먼저
termux-clipboard-set을 시도합니다.
- TS는 stdout이 TTY일 때 먼저 OSC 52 (
- 이미지 읽기 경로:
- Rust가
arboard에서 원시 이미지를 읽습니다. - Rust가 이를 PNG 바이트로 재인코딩하고 (
image크레이트),{ data: Uint8Array, mimeType: "image/png" }를 반환합니다. - TS는 Termux 또는 디스플레이 서버가 없는 Linux 세션(
DISPLAY/WAYLAND_DISPLAY누락)에서null을 조기 반환합니다.
- Rust가
작업 프로파일링 (work)
섹션 제목: “작업 프로파일링 (work)”- 수집 경계: 프로파일링 샘플은
task::blocking과task::future의profile_region(tag)가드에 의해 생성됩니다. - 저장 형식: 스택 경로 + 지속 시간 (
μs) + 타임스탬프 (프로세스 시작 이후 μs)를 저장하는 고정 크기 순환 버퍼 (MAX_SAMPLES = 10_000). - 출력 경계:
getWorkProfile(lastSeconds)는 다음 객체를 반환합니다:folded: 접힌 스택 텍스트 (플레임그래프 입력)summary: 마크다운 테이블 요약svg: 선택적 플레임그래프 SVGtotalMs,sampleCount
생명주기 및 상태 전이
섹션 제목: “생명주기 및 상태 전이”이미지 생명주기
섹션 제목: “이미지 생명주기”PhotonImage.parse(bytes)가 블로킹 디코드 작업을 스케줄링합니다 (image.decode).- 성공 시, 네이티브
PhotonImage핸들이 JS에 존재합니다. resize(...)는 새로운 네이티브 핸들을 생성하며 (image.resize), 이전 핸들과 새 핸들이 공존할 수 있습니다.encode(...)는 이미지 크기를 변경하지 않고 바이트를 구체화합니다 (image.encode).
실패 전이:
- 형식 감지/디코드 실패는 parse 프로미스를 거부합니다.
- 인코드 실패는 encode 프로미스를 거부합니다.
- 유효하지 않은 형식 ID는 encode 프로미스를 거부합니다.
HTML 생명주기
섹션 제목: “HTML 생명주기”htmlToMarkdown(html, options)가 블로킹 변환 작업을 스케줄링합니다.- 변환은 지정되지 않은 경우 기본 옵션 (
cleanContent=false,skipImages=false)으로 실행됩니다. - 마크다운 문자열을 반환하거나 거부합니다.
실패 전이:
- 변환기 실패는 거부된 프로미스를 반환합니다 (
Conversion error: ...).
클립보드 생명주기
섹션 제목: “클립보드 생명주기”copyToClipboard(text)는 의도적으로 최선 노력 방식이며 다중 경로입니다:
- TTY인 경우: OSC 52 쓰기를 시도합니다 (base64 페이로드).
TERMUX_VERSION이 설정된 경우 Termux 명령을 시도합니다.- 네이티브
arboard텍스트 복사를 시도합니다. - TS 계층에서 오류를 무시합니다.
readImageFromClipboard()의 엄격성은 단계별로 다릅니다:
- TS가 지원되지 않는 런타임 컨텍스트(Termux/헤드리스 Linux)를
null로 하드 게이트합니다. - Rust
arboard읽기는 TS가 허용한 경우에만 실행됩니다. ContentNotAvailable은null로 매핑됩니다.- 기타 Rust 오류는 거부합니다.
작업 프로파일링 생명주기
섹션 제목: “작업 프로파일링 생명주기”- 명시적 시작이 없습니다: 작업 헬퍼가 실행될 때 프로파일링이 항상 켜져 있습니다.
- 모든 계측된 작업 스코프는 가드 드롭 시 하나의 샘플을 기록합니다.
- 버퍼 용량에 도달하면 샘플이 가장 오래된 항목을 덮어씁니다.
getWorkProfile(lastSeconds)가 시간 윈도우를 읽고 접힌 스택/요약/SVG 아티팩트를 도출합니다.
실패 전이:
- SVG 생성 실패는 소프트 실패입니다 (
svg: null), 접힌 스택과 요약은 여전히 반환됩니다. - 빈 샘플 윈도우는 빈 접힌 데이터와
svg: null을 반환하며, 오류가 아닙니다.
지원되지 않는 작업 및 오류 전파
섹션 제목: “지원되지 않는 작업 및 오류 전파”이미지
섹션 제목: “이미지”- 지원되지 않는 디코드 입력 또는 손상된 바이트: 엄격한 실패 (프로미스 거부).
- 지원되지 않는 인코드 형식 ID: 엄격한 실패.
- TS 래퍼에 최선 노력 폴백 경로가 없습니다.
HTML
섹션 제목: “HTML”- 변환 오류는 엄격한 실패입니다 (거부).
- 옵션 생략은 최선 노력 기본값 적용이며, 실패가 아닙니다.
클립보드
섹션 제목: “클립보드”- 텍스트 복사는 TS 계층에서 최선 노력 방식입니다: 작동 실패가 억제됩니다.
- 이미지 읽기는 “이미지 없음” (
null)과 작동 실패 (거부)를 구분합니다. - Termux/헤드리스 Linux는 이미지 읽기에 대해 지원되지 않는 컨텍스트로 처리됩니다 (
null).
작업 프로파일링
섹션 제목: “작업 프로파일링”- 함수 호출 자체에 대한 검색은 엄격하지만, 아티팩트 생성은 부분적으로 최선 노력 방식입니다 (
svg는 null 가능). - 버퍼 잘림은 예상되는 동작(링 버퍼)이며, 데이터 손실 버그가 아닙니다.
플랫폼 주의사항
섹션 제목: “플랫폼 주의사항”- 클립보드 텍스트: OSC 52는 터미널 지원에 의존하며, 네이티브 클립보드 접근은 데스크톱 환경/세션에 의존합니다.
- 클립보드 이미지 읽기: Termux 및 디스플레이 서버가 없는 Linux에서는 TS에서 차단됩니다.