aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/lux/world/file.lux
blob: 3a729e93643f21f0578df5ef472d546aef540490 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
(.module:
  lux
  (lux (control [monad #+ do]
                ["ex" exception #+ exception:])
       (data (coll [array]))
       (time ["i" instant]
             ["d" duration])
       (world [blob #+ Blob])
       [io #+ Process]
       [host]))

(type: #export File Text)

(exception: #export (could-not-read-all-data {file File})
  file)

(exception: #export (not-a-directory {file File})
  file)

(host.import #long java/io/File
  (new [String])
  (exists [] #io #try boolean)
  (mkdirs [] #io #try boolean)
  (delete [] #io #try boolean)
  (length [] #io #try long)
  (listFiles [] #io #try #? (Array java/io/File))
  (getAbsolutePath [] #io #try String)
  (renameTo [java/io/File] #io #try boolean)
  (isFile [] #io #try boolean)
  (isDirectory [] #io #try boolean)
  (lastModified [] #io #try long)
  (setLastModified [long] #io #try boolean)
  (canRead [] #io #try boolean)
  (canWrite [] #io #try boolean)
  (canExecute [] #io #try boolean)
  (#static separator String))

(host.import java/lang/AutoCloseable
  (close [] #io #try void))

(host.import java/io/OutputStream
  (write [(Array byte)] #io #try void)
  (flush [] #io #try void))

(host.import java/io/FileOutputStream
  (new [java/io/File boolean] #io #try))

(host.import java/io/InputStream
  (read [(Array byte)] #io #try int))

(host.import java/io/FileInputStream
  (new [java/io/File] #io #try))

(do-template [<name> <flag>]
  [(def: #export (<name> data file)
     (-> Blob File (Process Unit))
     (do io.Monad<Process>
       [stream (FileOutputStream::new [(java/io/File::new file) <flag>])
        _ (OutputStream::write [data] stream)
        _ (OutputStream::flush [] stream)]
       (AutoCloseable::close [] stream)))]

  [append true]
  [write  false]
  )

(def: #export (read file)
  (-> File (Process Blob))
  (do io.Monad<Process>
    [#let [file' (java/io/File::new file)]
     size (java/io/File::length [] file')
     #let [data (blob.create (int-to-nat size))]
     stream (FileInputStream::new [file'])
     bytes-read (InputStream::read [data] stream)
     _ (AutoCloseable::close [] stream)]
    (if (i/= size bytes-read)
      (wrap data)
      (io.io (ex.throw could-not-read-all-data file)))))

(def: #export (size file)
  (-> File (Process Nat))
  (do io.Monad<Process>
    [size (java/io/File::length [] (java/io/File::new file))]
    (wrap (int-to-nat size))))

(def: #export (files dir)
  (-> File (Process (List File)))
  (do io.Monad<Process>
    [?files (java/io/File::listFiles [] (java/io/File::new dir))]
    (case ?files
      (#.Some files)
      (monad.map @ (java/io/File::getAbsolutePath [])
                 (array.to-list files))

      #.None
      (io.throw not-a-directory dir))))

(do-template [<name> <method>]
  [(def: #export (<name> file)
     (-> File (Process Bool))
     (<method> [] (java/io/File::new file)))]

  [exists?        java/io/File::exists]
  [make-directory java/io/File::mkdirs]
  [delete         java/io/File::delete]
  [file?          java/io/File::isFile]
  [directory?     java/io/File::isDirectory]
  [can-read?      java/io/File::canRead]
  [can-write?     java/io/File::canWrite]
  [can-execute?   java/io/File::canExecute]
  )

(def: #export (move target source)
  (-> File File (Process Bool))
  (java/io/File::renameTo [(java/io/File::new target)]
                          (java/io/File::new source)))

(def: #export (last-modified file)
  (-> File (Process i.Instant))
  (do io.Monad<Process>
    [millis (java/io/File::lastModified [] (java/io/File::new file))]
    (wrap (|> millis d.from-millis i.absolute))))

(def: #export (modify time file)
  (-> i.Instant File (Process Bool))
  (java/io/File::setLastModified [(|> time i.relative d.to-millis)]
                                 (java/io/File::new file)))

(def: #export separator Text java/io/File::separator)