golang.org/x/exp@v0.0.0-20240506185415-9bf2ced13842/mmap/mmap_other.go (about)

     1  // Copyright 2015 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build !linux && !windows && !darwin
     6  
     7  // Package mmap provides a way to memory-map a file.
     8  package mmap
     9  
    10  import (
    11  	"fmt"
    12  	"os"
    13  )
    14  
    15  // ReaderAt reads a memory-mapped file.
    16  //
    17  // Like any io.ReaderAt, clients can execute parallel ReadAt calls, but it is
    18  // not safe to call Close and reading methods concurrently.
    19  type ReaderAt struct {
    20  	f   *os.File
    21  	len int
    22  }
    23  
    24  // Close closes the reader.
    25  func (r *ReaderAt) Close() error {
    26  	return r.f.Close()
    27  }
    28  
    29  // Len returns the length of the underlying memory-mapped file.
    30  func (r *ReaderAt) Len() int {
    31  	return r.len
    32  }
    33  
    34  // At returns the byte at index i.
    35  func (r *ReaderAt) At(i int) byte {
    36  	if i < 0 || r.len <= i {
    37  		panic("index out of range")
    38  	}
    39  	var b [1]byte
    40  	r.ReadAt(b[:], int64(i))
    41  	return b[0]
    42  }
    43  
    44  // ReadAt implements the io.ReaderAt interface.
    45  func (r *ReaderAt) ReadAt(p []byte, off int64) (int, error) {
    46  	return r.f.ReadAt(p, off)
    47  }
    48  
    49  // Open memory-maps the named file for reading.
    50  func Open(filename string) (*ReaderAt, error) {
    51  	f, err := os.Open(filename)
    52  	if err != nil {
    53  		return nil, err
    54  	}
    55  	fi, err := f.Stat()
    56  	if err != nil {
    57  		f.Close()
    58  		return nil, err
    59  	}
    60  
    61  	size := fi.Size()
    62  	if size < 0 {
    63  		f.Close()
    64  		return nil, fmt.Errorf("mmap: file %q has negative size", filename)
    65  	}
    66  	if size != int64(int(size)) {
    67  		f.Close()
    68  		return nil, fmt.Errorf("mmap: file %q is too large", filename)
    69  	}
    70  
    71  	return &ReaderAt{
    72  		f:   f,
    73  		len: int(fi.Size()),
    74  	}, nil
    75  }